动态代理

108 阅读16分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1、private、final、static修饰的方法不能够被动态代理

final修饰的关键字不可变,不可继承不可重写。接口继承都不行

static不能修饰接口中的方法可以修饰抽象类的方法,static修饰的方法不能被继承

private修饰的方法不能被继承,子类都访问不到。接口实现类同样也访问不到

2、由于生成的代理类已经继承了proxy,所以只能通过实现接口来实现动态代理

3、java中不支持多继承的原因,因为如果两个父类有相同的方法,不同的实现子类再调用这个方法是根本就不知道调用哪一个。而接口可以有相同的实现,其方法在没有实现之前是没有意义的,实现的方法必须要实现。接口也算一种重写。

public class Mao implements Hummer {
    @Override
    public void init() {
        
    }
}

Spring中不支持直接对接口动态代理,因为Spring中的动态代理是在Bean实例化之后,而接口根本就实例化不了,Mybatis却可以,因为它走的不是Spring动态代理这一套逻辑

我们写的通知,如何实现的呢?

实际上切面类中的通知会被注册成一个通知,然后保存到一个集合中,每次扫描到Bean回去检查这个Bean能否匹配上切点,如果可以说明需要被增强,Cglib来说需要传入 MethodInterceptor调用invoke方法,该类的每一个方法都会调用 MethodInterceptor.intercept方法。内部会根据传入的方法,获取到匹配上的通知集合,如果为0直接调用方法不走通知,不为0,生成一个拦截器链执行通知方法,实际上是通过递归的方式,通过切面类反射执行通知方法。joinpoint.process就是执行下一个拦截器

实际上就是生成增强后的字节码文件然后通过类加载器加载。创建出代理对象。如何生成这个字节码文件的呢?

// 原代码
public class DynamicProxyTest {
    interface IHello {
        void sayHello();
    }

    static class Hello implements IHello {

        @Override
        public void sayHello() {
            System.out.println("hello world");
        }
    }
        
    // 代理对象需要invocationHandler作为构造函数,因为他需要通过这个方法调用增强后的方法
    static class DynamicProxy implements InvocationHandler {
        Object originalObj;

        Object bind(Object originalObj){
            this.originalObj = originalObj;
            return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
                    originalObj.getClass().getInterfaces(),this);
        }


        @Override
        public Object invoke(Object proxy, Method method, Object[] args) 
            throws Throwable {
            System.out.println("Like mao");
            return method.invoke(originalObj,args);
        }
    }
}


// 代理后代码  可以看出实际上是通过反射去调用方法的,对象则是InvocationHandler对象
// 通过静态代码块获取对应的方法对象。反射调用执行。
// 可以看出所有的代理对象都继承Proxy实现原接口。(Proxy对象持有InvocationHandler对象。而这个对象invoke是我们编写的增强逻辑)
// 此外特别的一个点是因为代理对象继承了Proxy所以只能通过实现接口的方式(不支持多继承)
final class $Proxy0 extends Proxy implements IHello {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
        
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void sayHello() throws  {
        try {
            // super.h 实际上就是InvocationHandler对象
            // 对于每一个方法都调用这个逻辑,而通过将传入的methed对象传入invoke增强了每一个方法。
            super h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
        
    //  类加载时获取需要代理的方法、默认是需要将equals、tostring、hashcode方法
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals");
            // 这里获取的是接口方法
            m3 = Class.forName("DynamicProxyTest$IHello").getMethod("sayHello");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{
    if (h == null) {
        throw new NullPointerException();
    }
    // 生成类,获取增强后的类
    Class cl = getProxyClass(loader, interfaces);
    try {
        // 将invocationHandler作为构造参数实例化代理对象
        Constructor cons = cl.getConstructor(constructorParams);
        return (Object) cons.newInstance(new Object[] { h });
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString());
    } catch (IllegalAccessException e) {
        throw new InternalError(e.toString());
    } catch (InstantiationException e) {
        throw new InternalError(e.toString());
    } catch (InvocationTargetException e) {
        throw new InternalError(e.toString());
    }
}

// 生成字节码的代码
private byte[] generateClassFile() {
    //第一步, 将所有的方法组装成ProxyMethod对象
    //首先为代理类生成toString, hashCode, equals等代理方法
    addProxyMethod(hashCodeMethod, Object.class);
    addProxyMethod(equalsMethod, Object.class);
    addProxyMethod(toStringMethod, Object.class);
    //遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象,
    for (int i = 0; i < interfaces.length; i++) {
        // 可以看出这里只获取接口的方法,并不是其他类
        Method[] methods = interfaces[i].getMethods();
        for (int j = 0; j < methods.length; j++) {
            // 添加到代理方法中
            addProxyMethod(methods[j], interfaces[i]);
        }
    }
    //对于具有相同签名的代理方法, 检验方法的返回值是否兼容
    for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
        checkReturnTypes(sigmethods);
    }

    //第二步, 组装要生成的class文件的所有的字段信息和方法信息
    try {
        //添加构造器方法
        methods.add(generateConstructor());
        //遍历需要添加的方法
        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
            for (ProxyMethod pm : sigmethods) {
                
                fields.add(new FieldInfo(pm.methodFieldName,
                        "Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC));
                //添加代理类的代理方法
                methods.add(pm.generateMethod());
            }
        }
        //添加代理类的静态字段初始化方法
        methods.add(generateStaticInitializer());
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }

    //验证方法和字段集合不能大于65535
    if (methods.size() > 65535) {
        throw new IllegalArgumentException("method limit exceeded");
    }
    if (fields.size() > 65535) {
        throw new IllegalArgumentException("field limit exceeded");
    }

    //第三步, 写入最终的class文件
    //验证常量池中存在代理类的全限定名
    cp.getClass(dotToSlash(className));
    //验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy"
    cp.getClass(superclassName);
    //验证常量池存在代理类接口的全限定名
    for (int i = 0; i < interfaces.length; i++) {
        cp.getClass(dotToSlash(interfaces[i].getName()));
    }
    //接下来要开始写入文件了,设置常量池只读
    cp.setReadOnly();

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    DataOutputStream dout = new DataOutputStream(bout);
    try {
        //1.写入魔数
        dout.writeInt(0xCAFEBABE);
        //2.写入次版本号
        dout.writeShort(CLASSFILE_MINOR_VERSION);
        //3.写入主版本号
        dout.writeShort(CLASSFILE_MAJOR_VERSION);
        //4.写入常量池
        cp.write(dout);
        //5.写入访问修饰符
        dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
        //6.写入类索引
        dout.writeShort(cp.getClass(dotToSlash(className)));
        //7.写入父类索引, 生成的代理类都继承自Proxy
        dout.writeShort(cp.getClass(superclassName));
        //8.写入接口计数值
        dout.writeShort(interfaces.length);
        //9.写入接口集合
        for (int i = 0; i < interfaces.length; i++) {
            dout.writeShort(cp.getClass(dotToSlash(interfaces[i].getName())));
        }
        //10.写入字段计数值
        dout.writeShort(fields.size());
        //11.写入字段集合
        for (FieldInfo f : fields) {
            f.write(dout);
        }
        //12.写入方法计数值
        dout.writeShort(methods.size());
        //13.写入方法集合
        for (MethodInfo m : methods) {
            m.write(dout);
        }
        //14.写入属性计数值, 代理类class文件没有属性所以为0
        dout.writeShort(0);
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }
    //转换成二进制数组输出
    return bout.toByteArray();
}

1、代理对象class文件最重要的就是方法和字段了

1、收集所有接口的抽象方法,封装成抽象方法 2、遍历每一个抽象方法生成对应字段、以及方法信息

// 字段
private static Method m0;
// 方法信息
public final int hashCode() throws  {
    try {
        return (Integer)super.h.invoke(this, m0, (Object[])null);
    } catch (RuntimeException | Error var2) {
        throw var2;
    } catch (Throwable var3) {
        throw new UndeclaredThrowableException(var3);
    }
}
// 最后开始组装class 比如魔数、版本号、方法、字段、修饰符等等,然后生成字节码文件

获取动态代理生成的class文件

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\Users\50213\Desktop\class");
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

Cglib动态代理生成的代理对象class。會為每一個方法生成一個原有方法,和代理方法MethodProxy。

Cglib和JDK的底層不同的是,前者通過對象調用方法形式實現,而後者通過反射實現。

Cglib創建代理對象會生成三個類,一個代理類,兩個FastClass類。

FastClass説白了就是將方法名與方法調用做一個映射,

@Override
// 这里传进来的obj是代理对象
// method,目标对象的方法
public Object intercept(Object obj, Method method, Object[] args,
                        MethodProxy proxy) throws Throwable {
    // 说白了这种方式实际走的还是反射srcTarget原对象  
    Object o = method.invoke(srcTarget, args);
    // 这里就是直接通过父类调用原方法,性能高。内部是通过switch来确定到底调用哪一个方法
    proxy.invokeSuper(obj,args);
    return o;
}

// 下面两种方式的区别
// MethodProxy的两个方法
public Object invoke(Object obj, Object[] args) throws Throwable {
    try {
        init();
        FastClassInfo fci = fastClassInfo;
        // 这里调用的fastClass 而这个回调了getPeriod,这样做会又会调用回自己进入死循环
        // i1是增强后方法的下标
        return fci.f1.invoke(fci.i1, obj, args);
    }
}

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        init();
        FastClassInfo fci = fastClassInfo;
        // 这里调用的fastClass  实际上回调了CGLIB$getPeriod$1()
        // i2是未增强的下标,作为switch(int num)
        return fci.f2.invoke(fci.i2, obj, args);
    }
}
public class hotTask$$EnhancerBySpringCGLIB$$52b7866f extends hotTask implements SpringProxy, Advised, Factory {
    private boolean CGLIB$BOUND;
    // 线程相关的回调函数
    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
    // 静态可以用来保存代理对象共有的回调函数
    private static final Callback[] CGLIB$STATIC_CALLBACKS;
    // 用户定义的回调函数,回调函数不是静态的所以每一次创建对象都需要对回调函数赋值
    private MethodInterceptor CGLIB$CALLBACK_0;
    // 这些也是回调函数
    private MethodInterceptor CGLIB$CALLBACK_1;

    // 會為每一個方法生成一個原有方法,和代理方法MethodProxy。
    private static final Method CGLIB$getPeriod$1$Method;
    private static final MethodProxy CGLIB$getPeriod$1$Proxy;
  
        // 在下方静态代码块自动执行
    static void CGLIB$STATICHOOK29() {
        CGLIB$THREAD_CALLBACKS = new ThreadLocal();
        CGLIB$emptyArgs = new Object[0];
        // 生成的代理对象class对象
        Class var0 = Class.forName(
            "com.qianqi.community.quartz.task.hotTask$$EnhancerBySpringCGLIB$$52b7866f"
        );
        ...
        Method[] var10000 = ReflectUtils.findMethods(
            new String[]{"getPeriod"...}, (
                var1 = Class.forName("com.qianqi.community.quartz.JobBean"))
            .getDeclaredMethods());
        
        // 获取到target类中相应的方法对象
        CGLIB$getPeriod$1$Method = var10000[0];
        // 获取到代理类中相应的方法
        CGLIB$getPeriod$1$Proxy = MethodProxy.create(var1, var0, "()I", "getPeriod", "CGLIB$getPeriod$1");
    }
    
    // 设置回调函数的方法,通过ThreadLocal进行设置的
    public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) {
        hotTask$$EnhancerByCGLIB$$6f07c3f7.CGLIB$THREAD_CALLBACKS.set(array);
    }
    
    // CGLIB$getPeriod$1$Method方法的具体实现
    final int CGLIB$getPeriod$1() {
        return super.getPeriod();
    }
    // CGLIB$getPeriod$1$Proxy方法的具体实现
    public final int getPeriod() {
        // 获取用户传入的回调函数
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            // 如果用户没有设置 从threadLocal || static 获取回调函数
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }
        if (var10000 != null) {
            // 调用回调函数的intercept方法,传入this,原方法,空参,代理后的方法
            // callable中是MethodInterceptor
            Object var1 = var10000.intercept(
                this, 
                CGLIB$getPeriod$1$Method, 
                CGLIB$emptyArgs, 
                CGLIB$getPeriod$1$Proxy
            );
            // 参数返回null,返回0
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            // 最后没有回调方法,则调用父类的原逻辑
            return super.getPeriod();
        }
    }
        // 回调函数初始化,参数是代理对象
    private static final void CGLIB$BIND_CALLBACKS(Object var0) {
        hotTask$$EnhancerBySpringCGLIB$$52b7866f var1 = 
            (hotTask$$EnhancerBySpringCGLIB$$52b7866f)var0;
        // 只绑定一次
        if (!var1.CGLIB$BOUND) {
            var1.CGLIB$BOUND = true;
            // 首先从ThreadLocal中获取
            Object var10000 = CGLIB$THREAD_CALLBACKS.get();
            if (var10000 == null) {
                // 静态获取
                var10000 = CGLIB$STATIC_CALLBACKS;
                if (var10000 == null) {
                    return;
                }
            }
            // 一般用不怎么到
            Callback[] var10001 = (Callback[])var10000;
            // 固定的那几个处理函数
            var1.CGLIB$CALLBACK_6 = (MethodInterceptor)((Callback[])var10000)[6];
            var1.CGLIB$CALLBACK_5 = (MethodInterceptor)var10001[5];
            var1.CGLIB$CALLBACK_4 = (Dispatcher)var10001[4];
            var1.CGLIB$CALLBACK_3 = (Dispatcher)var10001[3];
            var1.CGLIB$CALLBACK_2 = (NoOp)var10001[2];
            var1.CGLIB$CALLBACK_1 = (MethodInterceptor)var10001[1];
            // 执行拦截器链的MethodIntercept
            var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
        }

    }

    static {
        CGLIB$STATICHOOK29();
    }

public class hotTask$$EnhancerBySpringCGLIB$$52b7866f$$FastClassBySpringCGLIB$$ea58f146 extends FastClass{
    // 这个invoke调用的是上面那个类的var10000.CGLIB$run$0();增强方法
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        52b7866f var10000 = (52b7866f)var2;
        int var10001 = var1;
        try {
            switch(var10001) {
            case 0:
                var10000.run();
                return null;
            case 1:
                return new Boolean(var10000.equals(var3[0]));
                  ...
            case 11:
                return new Integer(var10000.getPeriod());
            case 12:
                return var10000.getDescription();
            case 13:
                var10000.CGLIB$run$0();
                return null;
            
            case 16:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
            }
        }
        }
}

Spring中AOP的实现

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.Proxy;
import org.springframework.aop.SpringProxy;
import org.springframework.core.NativeDetector;
import org.springframework.util.ClassUtils;

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
    private static final long serialVersionUID = 7930414337282325166L;

    public DefaultAopProxyFactory() {
    }

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // isOptimize()判断是否需要进行优化,较早的版本,CGLIB的效率比JDK要好
        // isProxyTargetClass是否为类进行动态代理
        if (NativeDetector.inNativeImage() || !config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            // 这里直接返回代理对象啦
            return new JdkDynamicAopProxy(config);
        } else {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) && !ClassUtils.isLambdaClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }
    
    // 是否添加了接口,如果没有添加使用Cglib
    private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
        Class<?>[] ifcs = config.getProxiedInterfaces();
        return ifcs.length == 0 || ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0]);
    }
}

JdkDynamicAopProxy

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
   /** Config used to configure this proxy. */
private final AdvisedSupport advised;

   private final Class<?>[] proxiedInterfaces;
   
   // 接口中是否定义了equals,默认false
   private boolean equalsDefined;
   
   // 接口是否定义了hashCode,默认false
   private boolean hashCodeDefined;

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
      Assert.notNull(config, "AdvisedSupport must not be null");
      if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
         throw new AopConfigException("No advisors and no TargetSource specified");
      }
      this.advised = config;
      // 当前类需要代理的接口,还会额外代理3个接口,SpringProxy,Advised和DecoratingProxy
      // DecoratingProxy用于获取代理对象的原对象
      // SpringProxy只是一个标记接口,标记代理对象是使用spring aop创建
      // Advised,实现该接口,允许代理对象动态添加通知
      this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
      findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
   }

   @Override
   public Object getProxy(@Nullable ClassLoader classLoader) {
      return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
   }
  
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
    
       TargetSource targetSource = this.advised.targetSource;
       Object target = null;
       
       try {
          // 如果接口中没有定义euqals,交给代理比较,实际上就是不拦截
          // 如果接口定义了那么,则会通过拦截后再调用
          if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
             return equals(args[0]);
          }
          else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
             return hashCode();
          }
          // DecoratingProxy接口中定义了一个方法getDecoratedClass,用来获取被代理的原始目标对象的类型
          else if (method.getDeclaringClass() == DecoratingProxy.class) {
              // 调用AopProxyUtils工具类的方法,内部通过循环遍历的方式,找到最原始的被代理的目标类
             return AopProxyUtils.ultimateTargetClass(this.advised);
          }
          // 调用的方法是Advised接口定义的方法时,走到这里执行
          方法来源于 Advised 接口,代理对象默认情况下会实现 Advised 接口,可以通过代理对象来动态向代理对象中添加通知等
          else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
             // Service invocations on ProxyConfig with the proxy config...
             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
          }
    
          Object retVal;
          
           //是否需要在threadLocal中暴露代理对象
          if (this.advised.exposeProxy) {
             // 将当前代理对象暴露在上下文中,在当前线程中可以通过静态方法
             // AopContext#currentProxy获取当前被暴露的动态代理
             oldProxy = AopContext.setCurrentProxy(proxy);
             setProxyContext = true;
          }
    
          target = targetSource.getTarget();
          Class<?> targetClass = (target != null ? target.getClass() : null);
    
          // 获取当前方法的拦截器对象
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
          if (chain.isEmpty()) {
             // 直接反射调用原对象方法
             Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
          }
          else {
             // 创建一个方法调用器(包含了代理对象、目标对象、调用的方法、参数、目标类型、方法拦截器链) 
             MethodInvocation invocation =
                   new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
             // 递归调用拦截器链
             retVal = invocation.proceed();
          }
    
          // 对返回值进行处理,如果返回值为自己,则将返回值替换为代理对象
          Class<?> returnType = method.getReturnType();
          if (retVal != null && retVal == target &&
                returnType != Object.class && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
             // Special case: it returned "this" and the return type of the method
             // is type-compatible. Note that we can't help if the target sets
             // a reference to itself in another returned object.
             retVal = proxy;
          }
          // 如果返回值为null,但方法返回类型为基本数据类型,无法转换抛出异常
          else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
             throw new AopInvocationException(
                   "Null return value from advice does not match primitive return type for: " + method);
          }
          return retVal;
       }
       finally {
           
           // isStatic为true,表示目标对象是单例的,同一个代理对象中所有方法共享一个目标对象
           // isStatic为false的时候,通常每次调用代理的方法,target对象是不一样的,所以方法调用之后需要进行释放,可能有些资源清理,连接的关闭等操作
          if (target != null && !targetSource.isStatic()) {
             // Must have come from TargetSource.
             targetSource.releaseTarget(target);
          }
          // 恢复原来ThreadLocal中的代理对象
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
    
    @Override
    public boolean equals(@Nullable Object other) {
       ...
    }
    
    @Override
    public int hashCode() {
       ...
    }
}

ObjenesisCglibAopProxy

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   try {
      // 获取被代理的类
      Class<?> rootClass = this.advised.getTargetClass();

      Class<?> proxySuperClass = rootClass;
      // 如果被代理的类时cglib创建的类
      if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
         // 将其父类最为被代理的类
         proxySuperClass = rootClass.getSuperclass();
         // 获取父类的接口
         Class<?>[] additionalInterfaces = rootClass.getInterfaces();
         for (Class<?> additionalInterface : additionalInterfaces) {
            this.advised.addInterface(additionalInterface);
         }
      }

      Enhancer enhancer = createEnhancer();
      if (classLoader != null) {
         enhancer.setClassLoader(classLoader);
         if (classLoader instanceof SmartClassLoader &&
               ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
         }
      }
      // 设置代理的父类
      enhancer.setSuperclass(proxySuperClass);
       // 设置被代理的接口[开发者硬编码指定的需要被代理的接口列表,SpringProxy,Advised],这个比jdk动态代理的方式少了一个DecoratingProxy接口
      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
      // 命名策略
      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
      // 字节码生成策略
      enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

      // 每一个方法的执行器链、rootClass,包括实现的接口的方法
      Callback[] callbacks = getCallbacks(rootClass);
      Class<?>[] types = new Class<?>[callbacks.length];
      for (int x = 0; x < types.length; x++) {
         types[x] = callbacks[x].getClass();
      }
      // fixedInterceptorMap only populated at this point, after getCallbacks call above
      enhancer.setCallbackFilter(new ProxyCallbackFilter(
            this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
      enhancer.setCallbackTypes(types);

      // Generate the proxy class and create a proxy instance.
      return createProxyClassAndInstance(enhancer, callbacks);
   }
}
getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
   // 是否将代理对象暴露在threadlocal
   boolean exposeProxy = this.advised.isExposeProxy();
   boolean isFrozen = this.advised.isFrozen();
   // 代理对象是否是单例
   boolean isStatic = this.advised.getTargetSource().isStatic();

   // 方法上有需要执行的拦截器时,会调用这个方法来处理
   Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

   // 没有拦截器需要执行时,通过这个处理,内部通过反射调用目标对象的方法
   Callback targetInterceptor;
   if (exposeProxy) {
      targetInterceptor = (isStatic ?
            new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
   }
   else {
      targetInterceptor = (isStatic ?
            new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
            new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
   }

   // 直接调用目标对象
   Callback targetDispatcher = (isStatic ?
         new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

   Callback[] mainCallbacks = new Callback[] {
         aopInterceptor,   // 处理匹配到拦截器的方法
         targetInterceptor,   // 处理未匹配到拦截器的方法,并且方法返回值为目标对象类型用这个,返回代理后的对象
         new SerializableNoOp(),  
         targetDispatcher,  // 处理未匹配到拦截器的方法
         this.advisedDispatcher, // 处理Advised接口中定义的方法
         new EqualsInterceptor(this.advised), // 处理equals方法
         new HashCodeInterceptor(this.advised) // 处理hashCode方法
   };

   Callback[] callbacks;
   
   // 如果被代理的对象冻结的,生成好的代理中通知不可改变
   // 提前将每一个方法对应的拦截器链缓存起来
   if (isStatic && isFrozen) {
      Method[] methods = rootClass.getMethods();
      Callback[] fixedCallbacks = new Callback[methods.length];
      this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

      // 遍历每一个方法
      for (int x = 0; x < methods.length; x++) {
         Method method = methods[x];
         // 获取到对应方法的拦截器链
         List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
         // 缓存起来
         fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
               chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
         // 方法与下标做一个映射
         this.fixedInterceptorMap.put(method, x);
      }

      callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
      System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
      System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
      // 记录分割点
      this.fixedInterceptorOffset = mainCallbacks.length;
   }
   else {
      callbacks = mainCallbacks;
   }
   // 包含执行器链、目标对象
   return callbacks;
}
ProxyCallbackFilter.accept
// 主要是根据method匹配mainCallbacks中的拦截器
@Override
public int accept(Method method) {
   if (AopUtils.isFinalizeMethod(method)) {
      logger.trace("Found finalize() method - using NO_OVERRIDE");
      return NO_OVERRIDE;
   }
   // Advised中的方法,返回值是自己。targetInterceptor
   if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
         method.getDeclaringClass().isAssignableFrom(Advised.class)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Method is declared on Advised interface: " + method);
      }
      return DISPATCH_ADVISED;
   }
   // EqualsInterceptor(this.advised)
   if (AopUtils.isEqualsMethod(method)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Found 'equals' method: " + method);
      }
      return INVOKE_EQUALS;
   }
   // HashCodeInterceptor(this.advised)
   if (AopUtils.isHashCodeMethod(method)) {
      if (logger.isTraceEnabled()) {
         logger.trace("Found 'hashCode' method: " + method);
      }
      return INVOKE_HASHCODE;
   }
   Class<?> targetClass = this.advised.getTargetClass();
   // Proxy is not yet available, but that shouldn't matter.
   List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
   boolean haveAdvice = !chain.isEmpty();
   boolean exposeProxy = this.advised.isExposeProxy();
   boolean isStatic = this.advised.getTargetSource().isStatic();
   boolean isFrozen = this.advised.isFrozen();
   if (haveAdvice || !isFrozen) {
      // If exposing the proxy, then AOP_PROXY must be used.
      if (exposeProxy) {
         if (logger.isTraceEnabled()) {
            logger.trace("Must expose proxy on advised method: " + method);
         }
         return AOP_PROXY;
      }
      
      // 从缓存中获取
      if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(method)) {
         if (logger.isTraceEnabled()) {
            logger.trace("Method has advice and optimizations are enabled: " + method);
         }
         // We know that we are optimizing so we can use the FixedStaticChainInterceptors.
         int index = this.fixedInterceptorMap.get(method);
         return (index + this.fixedInterceptorOffset);
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Unable to apply any optimizations to advised method: " + method);
         }
         return AOP_PROXY;
      }
   }
   else {
      if (exposeProxy || !isStatic) {
         return INVOKE_TARGET;
      }
      Class<?> returnType = method.getReturnType();
      if (targetClass != null && returnType.isAssignableFrom(targetClass)) {
         if (logger.isTraceEnabled()) {
            logger.trace("Method return type is assignable from target type and " +
                  "may therefore return 'this' - using INVOKE_TARGET: " + method);
         }
         return INVOKE_TARGET;
      }
      else {
         if (logger.isTraceEnabled()) {
            logger.trace("Method return type ensures 'this' cannot be returned - " +
                  "using DISPATCH_TARGET: " + method);
         }
         return DISPATCH_TARGET;
      }
   }
}

主要是拦截器对象

  • DynamicAdvisedInterceptor
  • StaticUnadvisedExposedInterceptor
  • StaticUnadvisedInterceptor
  • DynamicUnadvisedInterceptor
  • StaticDispatcher
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
    //代理配置信息
    private final AdvisedSupport advised;
    //构造器,需要一个AdvisedSupport
    public DynamicAdvisedInterceptor(AdvisedSupport advised) {
        this.advised = advised;
    }

    //这个方法是关键,用来处理代理对象中方法的调用
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //被暴露在threadLocal中旧的代理对象
        Object oldProxy = null;
        //用来标记代理对象是否被暴露在threadLocal中
        boolean setProxyContext = false;
        //目标对象
        Object target = null;
        //目标源
        TargetSource targetSource = this.advised.getTargetSource();
        try {
            //代理配置中是否需要将代理暴露在threadLocal中
            if (this.advised.exposeProxy) {
                //将代理对象暴露出去
                oldProxy = AopContext.setCurrentProxy(proxy);
                //将setProxyContext置为true
                setProxyContext = true;
            }
            //获取目标对象(即被代理的对象)
            target = targetSource.getTarget();
            Class<?> targetClass = (target != null ? target.getClass() : null);
            //@1:获取当前方法的拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
            //记录方法返回值
            Object retVal;
            //拦截器链不为空 && 方法是public类型的
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                //获取方法调用参数
                Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                // 直接调用目标对象的方法
                retVal = methodProxy.invoke(target, argsToUse);
            }
            else {
                // 创建一个方法调用器(包含了代理对象、目标对象、调用的方法、参数、目标类型、方法拦截器链)
                // @2:并执行方法调用器的processd()方法,此方法会一次执行方法调用链,最终会调用目标方法,获取返回结果
                retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
            }
            // 处理方法返回结果:会根据方法返回值的类型,做一些处理,比如方法返回的类型为自己,则最后需要将返回值置为代理对象
            retVal = processReturnType(proxy, target, method, retVal);
            return retVal;
        }
        finally {
            // 目标对象不为null && 目标源不是静态的
            //所谓静态的,你可以理解为是否是单例的
            // isStatic为true,表示目标对象是单例的,同一个代理对象中所有方法共享一个目标对象
            // isStatic为false的时候,通常每次调用代理的方法,target对象是不一样的,所以方法调用万之后需要进行释放,可能有些资源清理,连接的关闭等操作
            if (target != null && !targetSource.isStatic()) {
                targetSource.releaseTarget(target);
            }
            // setProxyContext为ture
            if (setProxyContext) {
                // 需要将旧的代理再放回到上线文中
                AopContext.setCurrentProxy(oldProxy);
            }
        }
    }
}

Cglib高级操作

public class Service1 {

    public void m1(){
        System.out.println("m1");
        this.m2();
    }

    public void m2(){
        System.out.println("m2");
    }
    
    public Service1 getService1(){
        return this;
    }
}

@Test
public void testAop8(){
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.setTarget(new Service1());
    // 允许动态的添加修改通知
    proxyFactory.addAdvice(new MethodInterceptor() {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println(String.format("进入%s方法",invocation.getMethod().getName()));
            long startTime = System.nanoTime();
            Object proceed = invocation.proceed();
            long endTime = System.nanoTime();
            System.out.println(endTime - startTime);
            return proceed;
        }
    });
    // 获取代理对象
    Service1 proxy = (Service1)proxyFactory.getProxy();
    /*
    *   进入m1方法
        m1
        m2
        6756129701
        由于m2是this对象调用,并不是代理对象,如何让m2也是代理对象调用呢?
    */
    proxy.m1();
    // 可以获取到代理对象
    System.out.println(proxy.getService1());
}

1、可以设置一个构造器指向自己,我可以尝试一下(这个没试过)
2、编写一个方法,返回Service1对象,因拦截方法会将其替换为代理对象这是一个特例(方法2不行,必须是代理对象的方法)
3、将代理对象暴露到ThreadLocal,这样就可以在目标对象中获取到代理对象了
4、可以设置一个外界方法设置一个属性,只不过这样不优雅

实例的创建

JDK

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{
    Objects.requireNonNull(h);

    final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }

    /*
     * Look up or generate the designated proxy class.
     */
    Class<?> cl = getProxyClass0(loader, intfs);

    /*
     * Invoke its constructor with the designated invocation handler.
     */
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }

        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
        // 在构造函数中将InvocationHandler传入
        return cons.newInstance(new Object[]{h});
    } catch (IllegalAccessException|InstantiationException e) {
        throw new InternalError(e.toString(), e);
    } catch (InvocationTargetException e) {
        Throwable t = e.getCause();
        if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new InternalError(t.toString(), t);
        }
    } catch (NoSuchMethodException e) {
        throw new InternalError(e.toString(), e);
    }
}

Cglib

public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
   // 实际上就是通过反射调用代理对象中的CGLIB$SET_THREAD_CALLBACKS方法设置回调方法
   setThreadCallbacks(callbacks);
   try {
      // Explicit reference equality is added here just in case Arrays.equals does not have one
      if (primaryConstructorArgTypes == argumentTypes ||
            Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
         // If we have relevant Constructor instance at hand, just call it
         // This skips "get constructors" machinery
         return ReflectUtils.newInstance(primaryConstructor, arguments);
      }
      // 创建代理对象
      return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
   }
   finally {
      // clear thread callbacks to allow them to be gc'd
      setThreadCallbacks(null);
   }
}

重点要使创建出来的代理对象能有正常功能,必须要走Spring AOP的这个流程,比如JDK需要在jdk构造函数中传入JdkDynamicAopProxy,不走这个流程就不会传入,调用invoke就会调用抛异常,甚至JDK都无法实例化,Cglib虽然可以实例化,但是没有设置setThreadCallBack就会导致调用方法时就会抛出异常,底层Cglib的调用还是通过CallBack调用(MethodIntercept)

总结

Cglib创建代理对象的过程以及调用过程

1、获取目标对象,如果目标对象也是一个代理对象,那么获取代理对象的superClass

2、通过Enhance创建代理对象,设置父类,设置接口(包含SpringProxy、Advise)获取回调函数CallBack(6个固定的MethodIntercept,主要处理接口以及执行拦截器链)

3、创建出代理对象

执行过程,会两个类fastClass,一个代理对象,fastClass主要是调用父类的方法,本质上是switch然后通过父类对象调用原方法,这点与JDK完全不同

代理对象会有一个静态代码块用于设置回调方法,我们执行代理方法是,实际上是调用MethodIntercept.intercept(代理对象,目标方法对象,参数,代理方法对象)

代理方法对象两个方法

invoke调用代理对象的方法,这样会造成死循环

invokeSuper调用父类方法

实际上方法最终的调用是通过CallBack完成的,它作为一个数组赋值给代理对象的属性,如果不对CallBack初始化调用时就会出现空指针异常,我就碰到过

JDK创建代理对象

JdkDynamicAopProxy本身就是一个InvocationHandler

1、获取目标对象上的接口,同时会添加3个接口SpringProxy、Advise、DecoratingProxy装饰代理

2、JDK创建代理对象那一套,Proxy.newProxyInstance(类加载器,实现的接口,this)

代理对象最终调用的都是InvocationHandler.invoke,这里同样有一个静态代码块通过反射获取所有的method对象,调用invoke(代理对象,目标对象方法,参数)

重点就是JdkDynamicAopProxy中的invoke方法了

1、首先判断是不是hashCode、equals等这些方法,如果有任何一个接口包含了这个两个方法,那么就会走拦截流程,否则直接调用代理对象提供的equals、hashcode方法

2、如果是DecoratingProxy调用相应类处理

3、Advise同理

4、如果允许代理对象暴露,那么会设置到ThreadLocal中,之后获取该方法的拦截器链,如果没有直接反射调用原方法,否则走拦截器链逻辑。这就是全过程。