我是靠谱客的博主 失眠朋友,最近开发中收集的这篇文章主要介绍Spring之动态代理源码前言CGLIBJDK动态代理Work In Spring总结参考,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

在Spring之AOP的最后,我们提到了两种动态代理的方式:JDK动态代理以及cglib动态代理;JDK方式可以代理接口或者实现了接口的实现类,cglib的被代理类不能是接口/抽象类。本文基于JDK1.8

CGLIB

之前是在项目里引入spring全家桶来看源码的,所以一开始看Enhancer是在org.springframework下还以为是Spring自己重写的一套。通过jar包方式查看,发现很多相关的类都不能看到源码,就去github上拉了springframework;在spring-core这个模块下的spring-core.gradle有这么一段:

task cglibRepackJar(type: ShadowJar) {
	baseName = 'spring-cglib-repack'
	version = cglibVersion
	configurations = [project.configurations.cglib]
	relocate 'net.sf.cglib', 'org.springframework.cglib'
	relocate 'org.objectweb.asm', 'org.springframework.asm'
}

就是cglib用的还是net.sf.cglib,于是直接下了net.sf.cglib源码。附上地址:https://gitee.com/mirrors/cglib

源码

使用

我们先看一个例子,并想下打印出来是怎样的。

public class MyEnhancerTest {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyTest.class);
        enhancer.setCallback(new MyInterceptor());
        MyTest myTest = (MyTest) enhancer.create();
        myTest.print("hello world");
    }

    static class MyInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("前置操作");
            Object ret = proxy.invokeSuper(obj, args);
            System.out.println("后置操作");
            return ret;
        }
    }

    public void print(String input) {
        System.out.println(input + ":" + this.getClass().getName());
    }
}

现在我们看下打印的内容:

前置操作
hello world:MyEnhancerTest$$EnhancerByCGLIB$$49c4991a
后置操作

看打印的内容我们知道代理成功了,并且新的代理类名为MyEnhancerTest$$EnhancerByCGLIB$$49c4991a

输出代理类

在单元测试方法中加上

System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "target/cglib");

junit

就可以在target/cglib目录下输出cglib动态生成的类。
在这里插入图片描述
先了解下这3个类继承了什么父类,实现了什么接口。

public class MyEnhancerTest$$EnhancerByCGLIB$$49c4991a extends MyEnhancerTest implements Factory{}
public class MyEnhancerTest$$EnhancerByCGLIB$$49c4991a$$FastClassByCGLIB$$285c3a4a extends FastClass{}
public class MyEnhancerTest$$FastClassByCGLIB$$ef1ff622 extends FastClass{}

CGLIB是利用ASM框架来生成字节码文件的。ASM 是一个Java字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。

分析

使用中,我们看到打印出来的类名就是MyEnhancerTest$$EnhancerByCGLIB$$49c4991a,我们就从这个类开始进行分析吧。
类的内容比较多,我们按需粘贴代码进行分析,最好是在自己机器上执行一遍,看下类的全貌。

一进来首先是一个静态代码块CGLIB$STATICHOOK1()方法,CGLIB$STATICHOOK1()主要是初始化一些类属性。

static {
    CGLIB$STATICHOOK1();
}

static void CGLIB$STATICHOOK1() {
    CGLIB$THREAD_CALLBACKS = new ThreadLocal();
    CGLIB$emptyArgs = new Object[0];
    // 代理类
    Class var0 = Class.forName("MyEnhancerTest$$EnhancerByCGLIB$$49c4991a");
    // 父类,会根据方法而变动
    Class var1;
    Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
    CGLIB$equals$2$Method = var10000[0];
    CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
    CGLIB$toString$3$Method = var10000[1];
    CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
    CGLIB$hashCode$4$Method = var10000[2];
    CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
    CGLIB$clone$5$Method = var10000[3];
    CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
    // 这里var1赋值成`MyEnhancerTest`
    var10000 = ReflectUtils.findMethods(new String[]{"print", "(Ljava/lang/String;)V", "test", "()V"}, (var1 = Class.forName("MyEnhancerTest")).getDeclaredMethods());
    CGLIB$print$0$Method = var10000[0];
    // 根据父类/子类,以及两个类里的方法名生成`MethodProxy`, `MethodProxy`很重要,我们的`MethodInterceptor::intercept`就传入了这个参数
    CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "print", "CGLIB$print$0");
    CGLIB$test$1$Method = var10000[1];
    CGLIB$test$1$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$1");
}

MethodProxy.create方法将父/子类,以及方法信息存到MethodProxy中,后续会用到。

public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
    MethodProxy proxy = new MethodProxy();
    proxy.sig1 = new Signature(name1, desc);
    proxy.sig2 = new Signature(name2, desc);
    proxy.createInfo = new CreateInfo(c1, c2);
    return proxy;
}
public CreateInfo(Class c1, Class c2) {
    this.c1 = c1;
    this.c2 = c2;
    AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
    if (fromEnhancer != null) {
        namingPolicy = fromEnhancer.getNamingPolicy();
        strategy = fromEnhancer.getStrategy();
        attemptLoad = fromEnhancer.getAttemptLoad();
    }
}

当我们调用print方法时,执行的是这么一段代码。

public final void print(String var1) {
    // 我们之前在`Enhancer`里设置的`callback`, 这里就是`MyEnhancerTest.MyInterceptor`
    MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    if (var10000 == null) {
        CGLIB$BIND_CALLBACKS(this);
        var10000 = this.CGLIB$CALLBACK_0;
    }

    if (var10000 != null) {
        // 看到这里执行里`MyInterceptor`的`intercept`方法, 传入了当前对象,`MyEnhancerTest.print`的方法反射对象, 入参,以及`CGLIB$print$0$Proxy`(`CGLIB$print$0$Proxy`上文提过,是一个`MethodProxy`里面存储了父/子类以及`print`方法在两个类里的方法名)
        var10000.intercept(this, CGLIB$print$0$Method, new Object[]{var1}, CGLIB$print$0$Proxy);
    } else {
        super.print(var1);
    }
}

现在看看intercept里做了什么:

// 这一段是我们自己编写的代码,重点在`proxy.invokeSuper`
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("前置操作");
    Object ret = proxy.invokeSuper(obj, args);
    System.out.println("后置操作");
    return ret;
}
// `MethodProxy.invokeSuper`方法
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        // 生成fastClassInfo
        init();
        FastClassInfo fci = fastClassInfo;
        // 执行
        return fci.f2.invoke(fci.i2, obj, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException();
    }
}
// `MethodProxy.init`方法
private void init()
{
    if (fastClassInfo == null)
    {
        synchronized (initLock)
        {
            if (fastClassInfo == null)
            {
                // 这里保存了父/子类
                CreateInfo ci = createInfo;

                FastClassInfo fci = new FastClassInfo();
                // 利用cglib生成父类的FastClass
                fci.f1 = helper(ci, ci.c1);
                // 利用cglib生成子类的FastClass
                fci.f2 = helper(ci, ci.c2);
                // 通过`print`方法的签名获取该方法在fci.f1里的索引
                fci.i1 = fci.f1.getIndex(sig1);
                // 通过`CGLIB$print$0`方法的签名获取该方法在fci.f2里的索引
                fci.i2 = fci.f2.getIndex(sig2);
                fastClassInfo = fci;
                createInfo = null;
            }
        }
    }
}

我们在MethodProxy.init方法里生成了另外两个类MyEnhancerTest$$FastClassByCGLIB$$ef1ff622MyEnhancerTest$$EnhancerByCGLIB$$49c4991a$$FastClassByCGLIB$$285c3a4a。这里还有一个动作,就是getIndex。我们大概看下getIndex里的内容,了解下这个方法的作用:

public int getIndex(Signature var1) {
    String var10000 = var1.toString();
    switch(var10000.hashCode()) {
    case -1980342926:
        if (var10000.equals("print(Ljava/lang/String;)V")) {
            return 7;
        }
        break;
    case -1659779821:
        if (var10000.equals("CGLIB$test$1()V")) {
            return 20;
        }
        break;
    case -1457535688:
        if (var10000.equals("CGLIB$STATICHOOK1()V")) {
            return 22;
        }
        break;
    case -1422510685:
        if (var10000.equals("test()V")) {
            return 8;
        }
        break;
    case -623122092:
        if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
            return 21;
        }
        break;
    case 983548393:
        if (var10000.equals("CGLIB$print$0(Ljava/lang/String;)V")) {
            return 15;
        }
        break;
    ...
    return -1;
}

从代码猜测,getIndex方法的作用就是通过原始方法名获取一个索引,那这个索引怎么用呢?我们接下去看下执行的那步:

// fci.f2是的类是`MyEnhancerTest$$EnhancerByCGLIB$$49c4991a$$FastClassByCGLIB$$285c3a4a`, fci.i2是15
fci.f2.invoke(fci.i2, obj, args)

public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    49c4991a var10000 = (49c4991a)var2;
    int var10001 = var1;

    try {
        switch(var10001) {
        ...
        case 15:
            // 根据索引,执行方法
            var10000.CGLIB$print$0((String)var3[0]);
            return null;
        ...
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }

    throw new IllegalArgumentException("Cannot find matching method/constructor");
}

梳理下调用栈:

// 步骤1
MyEnhancerTest myTest = (MyEnhancerTest) enhancer.create();
myTest.print("hello world");

// 步骤2 `MyEnhancerTest$$EnhancerByCGLIB$$49c4991a`
public final void print(String var1) {
    MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    if (var10000 == null) {
        CGLIB$BIND_CALLBACKS(this);
        var10000 = this.CGLIB$CALLBACK_0;
    }

    if (var10000 != null) {
        var10000.intercept(this, CGLIB$print$0$Method, new Object[]{var1}, CGLIB$print$0$Proxy);
    } else {
        super.print(var1);
    }
}
// 步骤3 `MyInterceptor`
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println("前置操作");
    Object ret = proxy.invokeSuper(obj, args);
    System.out.println("后置操作");
    return ret;
}
// 步骤4 `MethodProxy`
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
    try {
        init();
        FastClassInfo fci = fastClassInfo;
        return fci.f2.invoke(fci.i2, obj, args);
    } catch (InvocationTargetException e) {
        throw e.getTargetException();
    }
}
// 步骤5 `MyEnhancerTest$$EnhancerByCGLIB$$49c4991a$$FastClassByCGLIB$$285c3a4a`
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
    49c4991a var10000 = (49c4991a)var2;
    int var10001 = var1;

    try {
        switch(var10001) {
        ...
        case 15:
            // var10000就是最前面调用`print`方法的`MyEnhancerTest$$EnhancerByCGLIB$$49c4991a`的对象
            var10000.CGLIB$print$0((String)var3[0]);
            return null;
        ...
    } catch (Throwable var4) {
        throw new InvocationTargetException(var4);
    }

    throw new IllegalArgumentException("Cannot find matching method/constructor");
}
// 步骤6 `MyEnhancerTest$$EnhancerByCGLIB$$49c4991a`
final void CGLIB$print$0(String var1) {
    // 调用父类的`print`方法
    super.print(var1);
}

JDK动态代理

源码

使用

public class JdkProxyTest {
    public static void main(String[] args) {

        MyInterface impl = new MyImpl();
        MyInterface o = (MyInterface) Proxy.newProxyInstance(MyImpl.class.getClassLoader(), MyImpl.class.getInterfaces(), new MyProxyHandler(impl));
        o.print("Hello World: " + o.getClass().getName());
    }

    interface MyInterface {
        void print(String str);
    }

    static class MyImpl implements MyInterface {
        @Override
        public void print(String str) {
            System.out.println(str);
        }
    }

    static class MyProxyHandler implements InvocationHandler {
        MyInterface target;

        public MyProxyHandler(MyInterface target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("前置操作: " + proxy.getClass().getName());
            Object ret = method.invoke(target, args);
            System.out.println("后置操作");
            return ret;
        }
    }
}

输出

前置操作: 
Hello World: $Proxy0
后置操作

从输出的信息可以看出,JDK帮我们生成了$Proxy0这个类,最终调用print方法还是我们原先创建的对象的方法。MyInterface target这个对象是我们传进来的,可以不传吗?可以的,JDK动态代理可以没有拦截对象,自己实现一些逻辑。

输出代理类

同样我们可以添加一个属性来输出代理类:

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

创建代理
我们同样在使用里看到了由JDK生成的类$Proxy0:proxy
看下这各类的继承及实现:

final class $Proxy0 extends Proxy implements MyInterface

分析

我们同样按需查看源码。
$Proxy0同样有一个静态代码块:

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            // 这里反射了`MyInterface`里的`print`方法
            m3 = Class.forName("JdkProxyTest$MyInterface").getMethod("print", Class.forName("java.lang.String"));
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }

我们直接来看调用$Proxy0.print

    public final void print(String var1) throws  {
        try {
        	// super.h就是我们的创建的`InvocationHandler` - `MyProxyHandler`
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("前置操作");
    // 就是在这里执行了我们这个代理对象时传入的被代理对象的`print`方法
    Object ret = method.invoke(target, args);
    System.out.println("后置操作");
    return ret;
}

method.invoke是怎么执行到我们目标类的目标方法的呢?

// java.lang.reflect.Method
public Object invoke(Object obj, Object... args)
    throws IllegalAccessException, IllegalArgumentException,
       InvocationTargetException
{
    //监测是否可以访问该方法
    if (!override) {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, obj, modifiers);
        }
    }
    MethodAccessor ma = methodAccessor;             // read volatile
    // 一开始都是null, 进入`acquireMethodAccessor`
    if (ma == null) {
        ma = acquireMethodAccessor();
    }
    return ma.invoke(obj, args);
}

从上面代码我们看到一个MethodAccessorMethodAccessor是什么呢?这里介绍下Method对象的基本构成,每个Java方法有且只有一个Method对象作为root,它相当于根对象,对用户不可见。这个root是不会暴露给用户的,当我们通过反射获取Method对象时,新创建Method对象把root包装起来再给用户,我们代码中获得的Method对象都相当于它的副本(或引用)。root对象持有一个MethodAccessor对象,所以所有获取到的Method对象都共享这一个MethodAccessor对象,因此必须保证它在内存中的可见性。下面我们看看这个MethodAccessor是怎么创建的。

private MethodAccessor acquireMethodAccessor() {
    MethodAccessor tmp = null;
    if (root != null) tmp = root.getMethodAccessor();
    // 一开始root里的`methodAccessor`为null
    if (tmp != null) {
        methodAccessor = tmp;
    } else {
        // Otherwise fabricate one and propagate it up to the root
        tmp = reflectionFactory.newMethodAccessor(this);
        setMethodAccessor(tmp);
    }

    return tmp;
}
//reflectionFactory.newMethodAccessor
public MethodAccessor newMethodAccessor(Method var1) {
    // 设置`ReflectionFactory`里的`noInflation`/`inflationThreshold`属性,这两个属性涉及到运行方式的转换
    checkInitted();
    if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
        // `generateMethod`里也用到了`ASM`技术
        return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
    } else {
        NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
        DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
        var2.setParent(var3);
        return var3;
    }
}
//生成`MethodAccessor`后,设置到对象里,这里对`root`结构也设置了
void setMethodAccessor(MethodAccessor accessor) {
    methodAccessor = accessor;
    // Propagate up
    if (root != null) {
        root.setMethodAccessor(accessor);
    }
}

Method.invoke方法里最终调用的是MethodAccessor.invoke,通过acquireMethodAccessor会有两种情况DelegatingMethodAccessorImpl或者MagicAccessorImpl; 我们看下方法实现:

// sun.reflect.DelegatingMethodAccessorImpl#invoke
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
    // 调用了`NativeMethodAccessorImpl`的`invoke`方法
    return this.delegate.invoke(var1, var2);
}
// sun.reflect.NativeMethodAccessorImpl#invoke
public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
    // 这里用到了上面提到的`inflationThreshold`;当执行次数达到一个设定的阈值时,创建了一个`MagicAccessorImpl`替换自己
    if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
        MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
        this.parent.setDelegate(var3);
    }

    return invoke0(this.method, var1, var2);
}

private static native Object invoke0(Method var0, Object var1, Object[] var2);

为什么要这样设计呢?这因为Java实现的版本在初始化时需要较多时间,但长久来说性能较好;native版本正好相反,启动时相对较快,但运行时间长了之后速度就比不过Java版了而native方式的初始化会更快,因此前几次的调用会采用native方法。随着调用次数的增加,每次反射都使用JNI跨越native边界会对优化有阻碍作用,相对来说使用拼装出的字节码可以直接以Java调用的形式实现反射,发挥了JIT优化的作用。

Work In Spring

以上内容分析了动态代理的工作原理。在这节里,我们跟Spring结合,看看它是怎么工作的。AbstractAutoProxyCreator通过createProxy创建代理,createProxy方法又委托给ProxyFactory创建代理;在createProxy方法中,给ProxyFactory对象设置了很多属性,包括增强器列表,targetSourceproxyTargetClass等;ProxyFactory由根据这些设置的属性来选择最终是通过JDK方式还是CGLIB方式来创建代理对象。JDK、CGLIB又是创建了怎样的代理对象使我们的Advisor能生效呢?接着看下面的分析吧。
我们将入口定位到:

// org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
    // createAopProxy方法JdkDynamicAopProxy或者ObjenesisCglibAopProxy
    // createAopProxy方法还将自己(ProxyFactory)传递给JdkDynamicAopProxy/ObjenesisCglibAopProxy作为这两个对象中的一个属性
	return createAopProxy().getProxy(classLoader);
}

JdkDynamicAopProxy

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    // advised就是生成这个proxy对象的`ProxyFactory`对象
    private final AdvisedSupport advised;
    
	public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
	}
	
	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		// 获取这个代理需要代理的接口,用于生成代理类
		// 会自动给我们加上`SpringProxy`, `Advised`, `DecoratingProxy`这三个接口
		Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
		// 在接口集合上查找是否有定义equals/hashCode方法
		// 有的话,就将equalsDefined、hashCodeDefined属性置为true
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		// 因为JdkDynamicAopProxy本身就是一个InvocationHandler,直接把自己作为一个处理程序传入
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}
}

至此,代理对象已经生成了。现在到非常关键的执行阶段,看下它的invoke方法吧:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
    // 这个targetSource很厉害,通过它,可以实现bean的多个scope。这里不展开说明了
	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
	    // 没有自定义的equals/hashCode方法就使用默认的实现
		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
			return equals(args[0]);
		}
		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
			return hashCode();
		}
		else if (method.getDeclaringClass() == DecoratingProxy.class) {
			// 调用的方法的定义来源于`DecoratingProxy`就返回this.advised的最终实现类
			// 这里是`ProxyFactory`
			return AopProxyUtils.ultimateTargetClass(this.advised);
		}
		else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
				method.getDeclaringClass().isAssignableFrom(Advised.class)) {
			// 调用的方法的定义来源于`Advised`及其子类
			// 直接执行this.advised里的相应方法
			return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
		}

		Object retVal;

		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// target是真正的被代理对象
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		// 获取这个方法被织入的增强
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		// 如果没有,就直接执行target里的相应方法
		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);
			// 执行增强列表
			// 这里可以思考一个问题,before/after这类方法增强是如何实现的
			retVal = invocation.proceed();
		}
        // 处理返回
		...
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

方法调用链

// org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
    // 当拦截器计数器达到总数-1时,让target执行
    // currentInterceptorIndex是从-1开始的
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}
    // 根据索引获取拦截器
	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	// 在获取这些增强时,如果是运行时的会增强会被InterceptorAndDynamicMethodMatcher包装
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		// 当前方法是否符合条件
		// 在获取的时候其实已经过滤一遍了方法与类了,这里再判断一下入参
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
		    // 在invoke里,通过改变MethodInvocation.proceed的位置来实现Before/After的效果
		    // Before/AfterReturn的位置很好放置,After的实现比较巧妙,是放在try{}finally{}的finally里
			return dm.interceptor.invoke(this);
		}
		else {
			// 如果不符合规则,就进行下一个
			// 因为在这个方法里this.currentInterceptorIndex用的是++
			return proceed();
		}
	}
	else {
		// 其他静态的拦截器,就直接执行,不用判断
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

ObjenesisCglibAopProxy

class ObjenesisCglibAopProxy extends CglibAopProxy {
	public ObjenesisCglibAopProxy(AdvisedSupport config) {
		super(config);
	}
}
class CglibAopProxy implements AopProxy, Serializable {

    // advised就是生成这个proxy对象的`ProxyFactory`对象
	protected final AdvisedSupport advised;

	/** Dispatcher used for methods on Advised. */
	private final transient AdvisedDispatcher advisedDispatcher;

	public CglibAopProxy(AdvisedSupport config) throws AopConfigException {
		Assert.notNull(config, "AdvisedSupport must not be null");
		if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
			throw new AopConfigException("No advisors and no TargetSource specified");
		}
		this.advised = config;
		this.advisedDispatcher = new AdvisedDispatcher(this.advised);
	}
	
    // 返回代理对象
    public Object getProxy(@Nullable ClassLoader classLoader) {
		...
		try {
			Class<?> rootClass = this.advised.getTargetClass();
			Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

			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);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// 配置Enhancer
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			// 目标类实现的接口
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			// 设置字节码生成策略
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
            // 获取回调,在传进来的Advisor基础上增加了一个内置的拦截器
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

		    // 设置回调
			return createProxyClassAndInstance(enhancer, callbacks);
		}catch...
	}
	
	private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
		boolean exposeProxy = this.advised.isExposeProxy();
		boolean isFrozen = this.advised.isFrozen();
		boolean isStatic = this.advised.getTargetSource().isStatic();

		// 第一个内置的MethodInterceptor,会依次调用我们的Advisor
		Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

		// 目标对象方法在这个拦截器里执行
		// Static/Dynamic的区别是目标对象的获取方式不同
		// Static就是传进来的目标对象
		// Dynamic是通过targetSource获取的
		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返回目标对象
		// 如果不是Static就啥也不做
		Callback targetDispatcher = (isStatic ?
				new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

		Callback[] mainCallbacks = new Callback[] {
				aopInterceptor,
				targetInterceptor,
				new SerializableNoOp(),
				targetDispatcher, 
				// advisedDispatcher这个对象里保存了advised
				this.advisedDispatcher,
				new EqualsInterceptor(this.advised),
				new HashCodeInterceptor(this.advised)
		};

		Callback[] callbacks;

		// 如果对象是静态的,进行一个优化,把方法对应的Advisor都找出来
		// 封装到一个FixedChainStaticTargetInterceptor
		if (isStatic && isFrozen) {
			Method[] methods = rootClass.getMethods();
			Callback[] fixedCallbacks = new Callback[methods.length];
			this.fixedInterceptorMap = new HashMap<>(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);
			}
            // 将mainCallback与对方法的callback合并
            // 这里有多个,那么到底执行哪个呢?
            // 在拿到callbacks后,对这个enhancer对设置了CallbackFilter
            // CallbackFilter里会根据一系列判断去选定一个callback,这里不展开了
			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;
	}
	
	// 创建enhancer
	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		enhancer.setInterceptDuringConstruction(false);
		enhancer.setCallbacks(callbacks);
		return (this.constructorArgs != null && this.constructorArgTypes != null ?
				enhancer.create(this.constructorArgTypes, this.constructorArgs) :
				enhancer.create());
	}
}

方法调用链

JdkDynamicAopProxy一样,cglib也是在MethodInteceptor里执行了一个方法调用链CglibMethodInvocation

private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
    @Nullable
	private final MethodProxy methodProxy;

	public CglibMethodInvocation(Object proxy, @Nullable Object target, Method method,
			Object[] arguments, @Nullable Class<?> targetClass,
			List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {

		super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);

		// Only use method proxy for public methods not derived from java.lang.Object
		this.methodProxy = (Modifier.isPublic(method.getModifiers()) &&
				method.getDeclaringClass() != Object.class && !AopUtils.isEqualsMethod(method) &&
				!AopUtils.isHashCodeMethod(method) && !AopUtils.isToStringMethod(method) ?
				methodProxy : null);
	}

	@Override
	@Nullable
	public Object proceed() throws Throwable {
		try {
			return super.proceed();
		}
		catch...
	}
}

看到CglibMethodInvocation是继承自ReflectiveMethodInvocation, dddd。

总结

本文先分析了jdk/cglib动态代理的实现源码,JDK1.8的JDK动态代理与CGLIB都用到里ASM技术。CGLIB用到了FastClass,FastClass将方法的调用都枚举出来,通过方法签名进行索引,在调用时是直接调用类.方法
最后一节通过Spring源码,将动态代理与AOP之间的是如何结合并实现切面功能讲解了一遍。

参考

https://www.cnblogs.com/qingchen521/p/8575761.html

最后

以上就是失眠朋友为你收集整理的Spring之动态代理源码前言CGLIBJDK动态代理Work In Spring总结参考的全部内容,希望文章能够帮你解决Spring之动态代理源码前言CGLIBJDK动态代理Work In Spring总结参考所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部