Skip to content

Latest commit

 

History

History
42 lines (39 loc) · 2.79 KB

PROXY.md

File metadata and controls

42 lines (39 loc) · 2.79 KB

动态代理

因Spring AOP中使用到了两种代理,所以将这两个代理单独提出来,做个整理。

  • JDK动态代理
  • CGLIB代理

JDK动态代理

原理:动态生成一个代理类,该类实现所有指定的接口,并继承java.lang.reflect.Proxy类, 然后将代理类通过类加载器加载到程序中(运行时加载,非编译时加载)。

  • 代理类内逻辑 代理类的实现并不包含实际的处理逻辑,而是调用了InvocationHandler中的invoke方法, 通过invoke方法来调用目标对象(需传入InvocationHandler中,如通过构造方法传入)中的目标方法 (在此期间对目标方法进行拓展操作,如调用目标方法前的通知等),或进行其他处理逻辑(可以不包含目标对象,如mybatis)。
/**
 * @param loader 指定代理对象的类加载器
 * @param interfaces 代理对象需要实现的接口,可以同时指定多个接口
 * @param handler 方法调用的实际处理者,代理对象的方法调用都会转发到handler类中的invoke方法
 */
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)

CGLIB代理

CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。

原理:动态生成一个代理类,该类继承目标对象的类,然后将代理类通过类加载器加载到程序中(运行时加载,非编译时加载)。

  • 代理类内逻辑 代理类会重写父类中的所有方法,在重写的方法中做如下处理:
    • 尝试获取MethodInterceptor对象
      • 如果对象不存在(即对象==null),则直接调用父类的方法
      • 如果存在,那么调用MethodInterceptor对象的intercept方法,在intercept方法中可进行目标方法的拓展操作,如调用目标方法前的通知等
// 创建加强器,用来创建代理类
Enhancer enhancer = new Enhancer();
// 为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
enhancer.setSuperclass(Xxx.class);
// 设置回调:对于代理类上所有方法的调用,都会调用MethodInterceptor的实现,而MethodInterceptor则需要实现intercept()方法进行拦截
enhancer.setCallback(new XxxInterceptor(new Xxx()));
// 创建代理类对象并返回
Xxx xxx = (Xxx) enhancer.create();

总结

  1. 目标对象有实现接口的话,使用JDK动态代理;没有实现接口,使用CGLIB代理
  2. JDK动态代理CGLIB代理都是在运行时生成并加载代理类,而不是编译时。
  3. JDK动态代理生成的代理类继承java.lang.reflect.Proxy类,并实现目标接口CGLIB代理生成的代理类继承目标对象的类。