概述
前言
在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");
就可以在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$$ef1ff622
与MyEnhancerTest$$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
:
看下这各类的继承及实现:
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);
}
从上面代码我们看到一个MethodAccessor
,MethodAccessor
是什么呢?这里介绍下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
对象设置了很多属性,包括增强器列表,targetSource
,proxyTargetClass
等;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总结参考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复