设计模式——代理模式

定义

        代理模式,顾名思义,就是由一个第三方中介去帮助客户去做一些事情,在Java中,就是一个代理类帮助目标类做一些额外的操作。

优点

        代理模式的优点在于灵活,可扩展目标类的功能。

缺点

        代理模式下的缺点也十分明显,就是多了一层代理类,执行效率会下降,除此之外,代理类也可能为了实现某种功能而搞得十分复杂。

静态代理

        通过新建一个代理类去实现某个接口(目标类也实现的接口),在代理类的方法中引入目标类并且调用目标类的方法,初次之外,加入一系列额外的、增强的方法。使用时,直接使用代理类的方法就可以实现对原目标类方法的增强。

代码示例:

public interface IService {
    void doSomething();
}

public class TargetService implements IService {
    public void doSomething() {
        // 实际业务逻辑
    }
}

public class ProxyService implements IService {
    private IService targetService;

    public ProxyService(IService targetService) {
        this.targetService = targetService;
    }

    public void doSomething() {
        // 在调用实际方法前可以执行一些操作
        System.out.println("Before doSomething...");
        targetService.doSomething();
        // 在调用实际方法后也可以执行一些操作
        System.out.println("After doSomething...");
    }
}

        

静态代理是在编译期间就已经确定代理类的代码,并且代理类和被代理类是一对一的关系。在使用静态代理时,需要手动编写代理类,并在代理类中调用被代理类的方法。静态代理的优点是简单、直观,缺点是每个被代理类都需要对应一个代理类,当被代理类很多时,会增加代码量和维护成本。

动态代理是在运行时动态生成代理类的代码,代理类不需要手动编写,而是通过Java的反射机制在运行时动态生成。动态代理的优点是可以减少代理类的数量,只需要一个代理类就可以代理多个被代理类,减少了代码量和维护成本。同时,动态代理也更加灵活,可以在运行时根据需要动态地增加、删除或修改代理行为。缺点是相比静态代理,动态代理的实现过程更加复杂。

总结来说,静态代理在编译期就确定代理类的代码,代理类和被代理类是一对一的关系;而动态代理是在运行时动态生成代理类的代码,可以代理多个被代理类,更加灵活。选择使用哪种代理方式取决于具体的需求和场景。

动态代理

        动态代理是指在程序运行时,动态的生成代理类并创建代理对象的技术。

实现方式

        目前,有两种实现方式,基于jdk的方式和基于Cglib的方式。        

Jdk

        使用jdk来实现动态代理,目标类必须实现某个接口,所谓接口式代理;并且代理类必须实现java.lang.reflect.InvocationHandler 接口,并且编写invoke()方法,此方法就是对目标类进行代理的行为方法,定义了增强信息,可以在调用目标方法前后添加额外的处理逻辑。

        Java 的 java.lang.reflect.Proxy 类是实现动态代理的核心类。在动态代理的工作过程中,Proxy 类为指定的接口生成代理类及其对象,并通过调用 InvocationHandler 接口实现方法的动态调用。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

1、定义接口

public interface IService {
    void doSomething();
}

2、目标类实现接口

public class TargetService implements IService {
    public void doSomething() {
        System.out.println("Do something in TargetService ");
    }
}

3、编写增强类

public class Intensifier {
    public void before(){
        System.out.println("do something before target method");
    }
    public void after(){
        System.out.println("do something after target method");
    }
}

4、代理类实现InvocationHandler接口

public class DemoInvocationHandler implements InvocationHandler {
    //需要代理的目标对象
    private Object target;
    //增强类对象
    private Intensifier intensifier;
    public DemoInvocationHandler(Object target,Intensifier intensifier) {
        this.target = target;
        this.intensifier = intensifier;
    }
    //代理对象要执行的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        intensifier.before();
        Object result = method.invoke(target, args);
        intensifier.after();
        return result;
    }
}

5、测试

public class Test {
    @Test
    public void testProxy(){
        //增强类对象
        Intensifier intensifier = new Intensifier();
        //目标类
        IService target= new TargetService();
        //方法拦截处理器
        
        DemoInvocationHandler handler= new DemoInvocationHandler (target,intensifier);
        //获取代理实例对象
        IService iService= (IService) Proxy.newProxyInstance(
                TargetService.class.getClassLoader(),//类加载器
                TargetService.class.getInterfaces(), //目标类所实现的所有接口
                handler//方法拦截处理器
        );
        iService.doSomething();
    }
}


 使用jdk去实现动态代理也不是不行,就是太限制了,目标类必须实现某个接口,为了解决这种限制,我们使用cglib去实现动态代理。

Cglib

cglib不需要目标类实现某接口,而是作为目标类的子类(通过Enhancer下的setSuperClass()方法设置目标类为父类),去实现业务增强,以实现动态代理。

maven坐标

         <dependency>
          <groupId>cglib</groupId>
          <artifactId>cglib</artifactId>
          <version>2.2.2</version>
      </dependency>

1、编写目标类

public class TargetService{
   public void doSomething(){
         System.out.println("Do something in TargetService ");
    }
}

2、编写增强类

public class Intensifier {
    public void before(){
        System.out.println("do something before target method");
    }
    public void after(){
        System.out.println("do something after target method");
    }
}

3、编写拦截类

public class CglibInterceptor implements MethodInterceptor {
    Intensifier intensifier;

    public CglibInterceptor(Intensifier intensifier) {
        this.intensifier = intensifier;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        intensifier.before();
        Object result = methodProxy.invokeSuper(o,objects);
        intensifier.after();
        return result;
    }
}

4、测试

  @Test
    public void testProxy(){
        Intensifier intensifier = new Intensifier();

        //得到方法拦截器
        CglibInterceptor interceptor=new CglibInterceptor(intensifier);
        //使用CGLIB框架生成目标类的子类(代理类)实现增强
        Enhancer enhancer = new Enhancer();
        //设置父类字节码
        enhancer.setSuperclass(TargetService.class);
        //设置拦截处理
        enhancer.setCallback(interceptor);
        TargetService service= (TargetService)enhancer.create();
        service.doSomething();
    }

完~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值