jdk 动态代理

参考:https://blog.csdn.net/jiankunking/article/details/52143504

 

一、什么是代理

  代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制访问。代理类负责为委托类预处理消息,过滤消息,转发消息,以及进行消息被委托类执行后的后续处理。

  为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者来看,两者没有区别。通过代理类这一中间层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托对象,同时也为实施不同控制策略预留了空间,从而在设计上获得更大的灵活性。Java 动态代理机制以巧妙的方式完美实践了代理模式的设计理念。

 

二、Java 动态代理类

  Java 动态代理类位于 java.lang.reflect 包下,一般主要涉及以下两个类:

  1) interface  InvocationHandler:该接口中仅定义一个方法

public Object invoke(Object obj, Method method, Object[] args);

 

  在实际使用是,第一个参数 obj 一般指代理类,method 是被代理方法,args 为该方法的参数数组。这个抽象方法在代理类中动态实现。

  2)Proxy:该类即为动态代理类,其中主要有

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException{}

 

  该方法返回代理类的一个实例,返回后的代理类可以当做被代理类使用(可以用被代理类在接口中声明过的方法)

  所谓 DynamicProxy 是这样一种 class:它是在运行时生成的 class,在生成它的时候必须提供一组 interfaces 给它,然后该 class 就宣称它实现了这些 interface。当然,这个 DynamicProxy 其实就是一个 Proxy,它不会替你做实质性的工作,在生成它的实例时,你必须提供一个 handler,由它接管实际的工作。

  在使用动态代理类时,我们必须实现 InvocationHandler 接口。通过这种方式,被代理的对象可以在运行时动态改变,从而实现了非常灵活的动态代理关系。

 

  动态代理步骤:

  • 创建一个实现接口 InvocationHandler 的类,它必须实现 invoke 方法
  • 创建被代理的类及接口
  • 通过 Proxy 的静态方法 newProxyInstance 创建一个代理
  • 通过代理调用方法

 

三、JDK 动态代理的实现

1. 创建接口

public interface DeptService {
    void saveDpet(Dept dept);
}

 

2. 创建实现类

public class DeptServiceImpl implements DeptService {
    @Override
    public void saveDpet(Dept dept) {
        System.out.println(" do saveDpet");
    }
}

 

3. 创建代理类

public class MyInvocation implements InvocationHandler {

    private Object target;

    public MyInvocation(Object target){
        this.target = target;
    }

    public <T> T getProxy(){
        return (T)Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new MyInvocation(target));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(" proxy do before ");
        method.invoke(target, args);
        System.out.println(" proxy do After ");
        return null;
    }
}

 

4. 调用

    @Test
    public void doProxy(){
        DeptService deptService = new MyInvocation(new DeptServiceImpl()).getProxy();
        deptService.saveDpet(new Dept());
    }

 

 

四、动态代理实现原理

  生成的代理类调用 saveDept 方法时,为什么会自动调用 InvocationHandlerImpl 的 invoke() 方法?

  因为 JDK 生成的最终真正代理类,它继承自 Proxy 并实现了我们定义的 DeptService 方法,在实现 接口方法的内部,通过反射调用了 InvocationHandlerImpl 的 invoke 方法。

 

posted @ 2020-08-31 11:24  停不下的时光  阅读(180)  评论(0编辑  收藏  举报