Spring的动态代理
AOP是一种编程思想,对于Spring而言实现AOP是通过动态代理实现的。当然对于其它框架或者组件而言不一定需要动态代理。某些时候静态的插入代码块逻辑也算是AOP的体现。
一.AOP中的概念
AOP主要由四点组成,分别是:切面、切点、连接点、通知
1.1 切面(Advisor)
切面由切点和通知组成。
1.2 切点(Pointcut)
表示切点,用来匹配一个或多个连接点,Advice与切点表达式是关联在一起的,Advice将会执行在和切点表达式所匹配的连接点上。通俗得来说切点就是多个连接点组成的多个是否触发切面逻辑的匹配逻辑。
1.3 通知(Advice)
我们将切面必须完成工作称为通知,切面的工作就是通知。通知有五种:前置通知(使用@Before)、后置通知(使用@After)、返回之后通知(使用@AfterReturning)、抛出异常通知(使用AfterThrowing)、环绕通知(使用@Around)
表示在一个特定连接点上所采取的动作。Advice分为不同的类型,后面详细讨论,在很多AOP框架中,包括Spring,会用Interceptor拦截器来实现Advice,并且在连接点周围维护一个Interceptor链
1.4 连接点(Join point)
所有可能触发AOP(拦截方法的点)就称之为连接点,通俗得来说就是一段判断是否触发切面逻辑的匹配逻辑。
二.动态代理
2.1 CGLIB动态代理
CGLIB动态代理,代理的目标是一个类。利用ASM字节码技术为需要代理的类生成一个类的子类,在子类中重写了父类中非final的方法。当代理对象调用父类中的方法时,通过拦截器进行拦截,执行代理类中的方法,对父类中的方法进行增强。后续详细分析
2.1.1 使用方法
TargetService target = new TargetService();
Class<?> clazz = target.getClass();
// 初始化增强器
Enhancer enhancer = new Enhancer();
// 设置被代理类的class
enhancer.setSuperclass(clazz);
// 设置代理逻辑
enhancer.setCallbacks(new Callback[] { new MethodInterceptor() {
/**
* cglib动态代理 代理逻辑
* @param o 代理对象
* @param method 目标方法(被代理的方法)
* @param objects 方法参数
* @param methodProxy 代理方法
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
// 执行被代理的方法
// Object result = methodProxy.invoke(target, objects);
// Object result = method.invoke(target, objects);
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("after...");
return result;
}
}, NoOp.INSTANCE });
enhancer.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
if ("exeProxy".equals(method.getName())) {
// 0:代理逻辑数组中的下标,表示如果方法的名子为exeProxy,就执行第一个代理逻辑
return 0;
} else {
// 执行第二个代理逻,即不增强
return 1;
}
}
});
TargetService cglibService = (TargetService) enhancer.create();
cglibService.exeProxy();
cglib执行目标方法的几种方式:
- Object result = method.invoke(target, objects);
- Object result = methodProxy.invoke(target, objects);
- Object result = methodProxy.invokeSuper(o, objects); // o:代理对象,表示执行代理方法的父类方法
2.1.2 Enhancer
cglib的增强器,它有下面几个属性。
Class superclass
设置被代理类的类型
Callback callbacks[]
代理逻辑数组,MethodInterceptor是个接口,继承Callback
public interface MethodInterceptor extends Callback {
/**
* cglib动态代理 代理逻辑
* @param o 代理对象
* @param method 目标方法(被代理的方法)
* @param objects 方法参数
* @param methodProxy 代理方法
*/
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
CallbackFilter callbackFilter
CallbackFilter是一个接口代表代理逻辑的滤器条件,accept返回的是callbacks数组的序号。有可能被代理类中某个方法执行Callbacks中第一个代理逻辑,某个方法执行Callbacks中第二个代理逻辑,callbackFilter能够灵活得决定被代理类哪些方法使用Callbacks中哪个代理逻辑。
public interface CallbackFilter {
/**
* 代理逻辑的序号
* @param var1 代理方法
*/
int accept(Method var1);
}
2.1.3 大概原理
让代理类保存到磁盘上
使用JVM参数 -Dcglib.debugLocation=路径
或者在执行的时候使用使用System.setProperty设置
System.setProperty("cglib.debugLocation", "路径");
public class TargetService$EnhancerByCGLIB$8f3249f7 extends TargetService implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private NoOp CGLIB$CALLBACK_1;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$exeProxy$1$Method;
private static final MethodProxy CGLIB$exeProxy$1$Proxy;
private static final Object[] CGLIB$emptyArgs;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.jackyun.test.TargetService$EnhancerByCGLIB$8f3249f7");
Class var1;
CGLIB$exeProxy$1$Method = ReflectUtils.findMethods(new String[]{"exeProxy", "()V"}, (var1 = Class.forName("com.jackyun.test.TargetService")).getDeclaredMethods())[0];
CGLIB$exeProxy$1$Proxy = MethodProxy.create(var1, var0, "()V", "exeProxy", "CGLIB$exeProxy$1");
}
final void CGLIB$exeProxy$1() {
super.exeProxy();
}
//被代理的方法逻辑被改写了
public final void exeProxy() {
// 获取代理逻辑
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$exeProxy$1$Method, CGLIB$emptyArgs, CGLIB$exeProxy$1$Proxy);
} else {
super.exeProxy();
}
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -2000138631:
if (var10000.equals("exeProxy()V")) {
return CGLIB$exeProxy$1$Proxy;
}
}
return null;
}
public TargetService$EnhancerByCGLIB$8f3249f7() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
TargetService$EnhancerByCGLIB$8f3249f7 var1 = (TargetService$EnhancerByCGLIB$8f3249f7)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
Callback[] var10001 = (Callback[])var10000;
var1.CGLIB$CALLBACK_1 = (NoOp)((Callback[])var10000)[1];
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)var10001[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
TargetService$EnhancerByCGLIB$8f3249f7 var10000 = new TargetService$EnhancerByCGLIB$8f3249f7();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
throw new IllegalStateException("More than one callback object required");
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
TargetService$EnhancerByCGLIB$8f3249f7 var10000 = new TargetService$EnhancerByCGLIB$8f3249f7;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
Object var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
case 1:
var10000 = this.CGLIB$CALLBACK_1;
break;
default:
var10000 = null;
}
return (Callback)var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
break;
case 1:
this.CGLIB$CALLBACK_1 = (NoOp)var2;
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0, this.CGLIB$CALLBACK_1};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
this.CGLIB$CALLBACK_1 = (NoOp)var1[1];
}
static {
CGLIB$STATICHOOK1();
}
}
2.2 JDK动态代理
JDK动态代理 代理的是接口,大概原理为在运行期间,JVM会根据被代理类生成一个$Proxy代理类 继承自Proxy并实现被代理类所实现的接口。通过反射调用被代理的方法。
目标类要实现这个接口,当然代理的方法也是接口里面可以被重写的方法。(这里简单说以下,jdk8的接口中可以定义成员方法,但是只能使用default修饰,可以被子类重写。jdk9的接口中,可以用私有的成员方法,私有方法外部是看不见的,子类无法重写。)
2.2.1 使用方法
// 获取被代理类的class
Class<?> targetClass = Target.class;
Class<?> tag = JdkProxyServiceImpl.class;
JdkProxyService service = (JdkProxyService) Proxy
.newProxyInstance(TargetService.class.getClassLoader(), new Class[] { JdkProxyService.class }, new InvocationHandler() {
/**
* jdk动态代理 代理逻辑
* @param o 代理对象
* @param method 目标方法
* @param objects 目标方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// 前置增强
return method.invoke(tag.newInstance(), args);
} catch (Exception e) {
// 异常增强
}finally {
// 后置增强
}
}
});
service.exe();
//执行被代理逻辑
targetObj.exe();
2.2.2 Proxy
proxy会为目标类在jvm中生成一个虚拟类
ClassLoader
一个类加载器,通常出入被代理类的类加载器或者是被代理接口的类加载器
Class[] interfaces,
代理类类实现的接口的Class对象数组。主要是包含了最重要的代理类需要实现的接口方法的信息
InvocationHandler
InvocationHandler 接口在 java.lang.reflect 包里。最主要的就是定义了 invoke( ) 方法。它就是假设在已经动态生成了最后的 proxy 代理对象,以及所有接口定义的方法 Method 对象以及方法的参数的情况下,定义我们要怎么调用这些方法的地方。
就是一段代理逻辑。invoke有三个参数分别是
- Object proxy 代理对象
- Method method 目标方法
- Object[] args 目标方法的参数
2.2.3 大概原理
让代理类保存到磁盘上
使用JVM参数 -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
或者在执行的时候使用使用System.setProperty设置
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
定义了一个接口
// 定义一个接口
public interface JdkTargetService {
void print(String content);
}
// 写一个被代理类
public class JdkTargetServiceServiceImpl implements JdkTargetService{
@Override
public void print(String content) {
System.out.println(content);
}
}
public final class $Proxy0 extends Proxy implements JdkTargetService {
private static Method m1;
private static Method m2;
private static Method m0;
private static Method m3;
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 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);
}
}
public final void print(String var1) throws {
try {
// h就是InvocationHandler
// 这里调用了InvocationHandler的invoke方法
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
// 初始化
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");
// 初始化目标方法
m3 = Class.forName("com.jackyun.test.JdkTargetService").getMethod("print", Class.forName("java.lang.String"));
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
看一下最后生成的Proxy类
2.3 区别总结
JDK是通过继承Proxy类实现目标接口
CGLIB是使用ASM创建代理类继承目标类,重写了被代理的方法
JDK动态代理是使用反射去调用目标方法的
CGLIB大部分时候使用的是FastClass委托去调用目标方法,当然也可以用反射,FastClass原理感兴趣可以去研究一下
2.4 ProxyFactory
在SpringAOP中,Spring对cglib和jdk动态代理进行封装,在使用ProxyFactory中,由某些参数自行去决定使用cglib还是jdk动态代理,Spring的事务,Aspject都是使用ProxyFactory去实现的。
2.3.1 使用方法
2.4.1.1 设置被代理目标
// 设置被代理对象(目标对象)
proxyFactory.setTarget(targetService);
// 设置代理类需要实现的接口
proxyFactory.setInterfaces(TargetInterface.class);
使用TargetSource
@Lazy就是使用该功能实现的参考
ContextAnnotationAutowireCandidateResolver#buildLazyResolutionProxy
TargetSource ts = new TargetSource() {
@Override
public Class<?> getTargetClass() {
return descriptor.getDependencyType();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public Object getTarget() {
Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
if (target == null) {
Class<?> type = getTargetClass();
if (Map.class == type) {
return Collections.emptyMap();
}
else if (List.class == type) {
return Collections.emptyList();
}
else if (Set.class == type || Collection.class == type) {
return Collections.emptySet();
}
throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
"Optional dependency not present for lazy injection point");
}
if (autowiredBeanNames != null) {
for (String autowiredBeanName : autowiredBeanNames) {
if (dlbf.containsBean(autowiredBeanName)) {
dlbf.registerDependentBean(autowiredBeanName, beanName);
}
}
}
return target;
}
@Override
public void releaseTarget(Object target) {
}
};
pf.setTargetSource(ts);
在最后执行被代理方法的时候会去取TargetSource的getTarget返回的对象,执行被代理的方法。
2.4.1.2 创建通知
TargetService targetService = new TargetService();
ProxyFactory proxyFactory = new ProxyFactory();
// 设置被代理对象(目标对象)
proxyFactory.setTarget(targetService);
// 设置代理接口
//proxyFactory.setInterfaces(TargetInterface.class);
// 设置方法前置通知
proxyFactory.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// 前置
}
});
// 设置方法环绕通知
proxyFactory.addAdvice(new org.aopalliance.intercept.MethodInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 环绕
return null;
}
});
// 设置方法后置通知
proxyFactory.addAdvice(new AfterReturningAdvice() {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
// 后置处理器
}
});
// 设置异常通知
proxyFactory.addAdvice(new ThrowsAdvice(){
});
// 获取代理对象
TargetService proxy = (TargetService) proxyFactory.getProxy();
proxy.exeProxy();
2.3.1.1.1 设置方法前置通知
继承MethodBeforeAdvice类 重写before方法
2.3.1.1.2 设置方法环绕通知
继承org.aopalliance.intercept.MethodInterceptor类重写invoke方法
需要在调用invocation.proceed()继续向下执行其它代理逻辑(如果有的话)和被代理方法
2.3.1.1.3 设置方法后置通知
继承AfterReturningAdvice 重写afterReturning方法,没有方法,需要定义一个名为afterThrowing的方法,参数为下面几种可以实现
- public void afterThrowing(Exception ex)
- public void afterThrowing(RemoteException)
- public void afterThrowing(Method method, Object[] args, Object target, Exception ex)
- public void afterThrowing(Method method, Object[] args, Object target, ServletException ex)
2.3.1.1.4 设置方法异常通知
继承ThrowsAdvice类
2.4.1.3 创建切点
public class TargetPointcut implements Pointcut {
@Override
public ClassFilter getClassFilter() {
// 类匹配器
// 类名为targetService才代理
return clazz -> "targetService".equals(clazz.getName());
}
@Override
public MethodMatcher getMethodMatcher() {
// 方法匹配器
return new MethodMatcher() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 方法名为exeProxy才代理
return "exeProxy".equals(method.getName());
}
// 是否运行时匹配
@Override
public boolean isRuntime() {
return false;
}
// 运行时匹配逻辑,isRuntime=true才会被调用
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return false;
}
};
}
}
2.4.1.3.1 类匹配器
public ClassFilter getClassFilter() {
return clazz -> "targetService".equals(clazz.getName());
}
2.4.1.3.2 方法匹配器
public MethodMatcher getMethodMatcher() {
// 方法匹配器
return new MethodMatcher() {
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 方法名为exeProxy才代理
return "exeProxy".equals(method.getName());
}
// 是否运行时匹配
@Override
public boolean isRuntime() {
return false;
}
// 运行时匹配逻辑,isRuntime=true才会被调用
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return false;
}
};
}
Spring提供的几个方法匹配器
- 静态方法匹配器StaticMethodMatcher
public abstract class StaticMethodMatcher implements MethodMatcher {
@Override
public final boolean isRuntime() {
return false;
}
@Override
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
// should never be invoked because isRuntime() returns false
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
}
}
- 动态方法匹配器DynamicMethodMatcher
public abstract class DynamicMethodMatcher implements MethodMatcher {
@Override
public final boolean isRuntime() {
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return true;
}
}
2.4.1.3.3 适配了匹配器的切点
- StaticMethodMatcherPointcut
public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {
private ClassFilter classFilter = ClassFilter.TRUE;
public void setClassFilter(ClassFilter classFilter) {
this.classFilter = classFilter;
}
@Override
public ClassFilter getClassFilter() {
return this.classFilter;
}
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
- DynamicMethodMatcherPointcut
public abstract class DynamicMethodMatcherPointcut extends DynamicMethodMatcher implements Pointcut {
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
2.4.1.4 创建切面
2.4.1.5 暴露代理
开启后在代理逻辑中会把代理对象设置到AopContext的线程变量中
//该属性默认是false
proxyFactory.setExposeProxy(true)
2.4.1.6 代理冻结
代表代理逻辑一旦产生,后续再添加或者修改通知/切面都不会生效。
//该属性默认是false
proxyFactory.setFrozen(true)
2.3.2 原理解析
2.3.2.1 创建代理对象
流程图
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// isOptimize:开启优化,optimize=true(Spring认为cglib性能比jdk好)
// 设置了proxyTargetClass为ture
// 判断被代理的对象是不是一个接口
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
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.");
}
// 再次判断被代理的对象是不是一个接口
// 是不是一个被jdk代理的对象,如果是继续使用jdk动态代理
// 是不是一个lambda匿名类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
2.3.2.1.1 JDK创建代理对象
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
PS:JdkDynamicAopProxy实现了InvocationHandler接口,所以代理逻辑就在它的invoke方法内
2.3.2.1.2 CGLIB创建代理对象
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// advised就是ProxyFactory本身
// 获取本次要被代理class
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)) {
// 获取被代理的真是class对象
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
// 获取本次要被代理class实现的接口
for (Class<?> additionalInterface : additionalInterfaces) {
// 添加到ProxyFactory的interfaces集合中
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 创建一个cglib增强器
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));
// 设置cglib的名称策略器
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 获取被代理的Callback
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);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
// exposeProxy属性(暴露代理)
boolean exposeProxy = this.advised.isExposeProxy();
// 冻结代理逻辑属性
boolean isFrozen = this.advised.isFrozen();
// targetSource 是不是静态的
// 静态的意思就是在编译期去调用TargetSource().getTarget()返回这个对象生成代理,
// 如果通过setTarget设置的目标类
// targetSource就是SingletonTargetSource,它的isStatic就是true。
// 动态的意思就是在编译期为TargetSource这个对象生成代理
// 运行期去调用TargetSource().getTarget()
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
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()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
// 正常的代理逻辑
aopInterceptor, // for normal advice
// 没有设置通知的情况下,并且方法返回了this,
// 或者开启了暴露AOP或者targetSource静态属性为false
// 就是直接请求目标方法,然后对结果做一些处理
targetInterceptor, // invoke target without considering advice, if optimized
// finalize方法不尝试代理
new SerializableNoOp(), // no override for methods mapped to this
// 没有设置通知的情况下,没有开启暴露aop或者targetSource静态属性为true
// 并且方法返回值不是this
// 也就是不满足targetInterceptor这个的时候都会使用这个
targetDispatcher,
// 被代理的方法本身是一个Advised
this.advisedDispatcher,
// equals方法
new EqualsInterceptor(this.advised),
// hashcode方法的代理逻辑
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
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);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
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;
}
public int accept(Method method) {
// 如果是finalize方法
if (AopUtils.isFinalizeMethod(method)) {
logger.trace("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
// 如果被代理的类实现了Advised
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;
}
// equals方法
// We must always proxy equals, to direct calls to this.
if (AopUtils.isEqualsMethod(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Found 'equals' method: " + method);
}
return INVOKE_EQUALS;
}
// hashcode方法
// We must always calculate hashCode based on the proxy.
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;
}
// targetSource属性是静态的,且设置了冰冻
// Check to see if we have fixed interceptor to serve this method.
// Else use the 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 {
// See if the return type of the method is outside the class hierarchy of the target type.
// If so we know it never needs to have return type massage and can use a dispatcher.
// If the proxy is being exposed, then must use the interceptor the correct one is already
// configured. If the target is not static, then we cannot use a dispatcher because the
// target needs to be explicitly released after the invocation.
// 开启了暴露AOP或者targetSource不是静态的
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
// 被代理的方法返回this
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;
}
}
}
2.3.2.2 代理逻辑
cglib的代理逻辑主要在
DynamicAdvisedInterceptor的intercept方法中
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
// 获取targetSource
TargetSource targetSource = this.advised.getTargetSource();
try {
// 如果设置了暴露AOP
if (this.advised.exposeProxy) {
// 添加到ThreadLocal
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 匹配适合的拦截器添加到集合,返回不一定是拦截器对象
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//拦截器链为空的情况下,表示这个方法上面没有找到任何增强的通知,那么会直接通过反射直接调用目标对象
// 私有的,equals,hashCode,toString方法也不需要被代理
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// 如果参数是可变参数,需要做一些适配处理
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 使用反射调用
retVal = invokeMethod(target, method, argsToUse, methodProxy);
}
else {
// 如果存在通知链
// 创建一个方法调用器
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)
// 执行调用器
.proceed();
}
//根据方法返回值的类型,做一些处理,比如方法返回的类型为自己,则最后需要将返回值置为代理对象
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// 执行一个钩子函数
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
匹配适合的拦截器/方法匹配器 添加到集合
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// 初始化一个处理适配切面的处理器
// 所有各种类型的advisor转为MethodInterceptor
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取所有Advisor
// ps:添加的时候所有的Advise都会被包装成一个DefaultPointcutAdvisor,pointcut为PointCut.TRUE
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
// 遍历
for (Advisor advisor : advisors) {
// region PointcutAdvisor类型切面
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// setPreFiltered 用于全局跳过类的匹配逻辑
// 判断类是否通过
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
// 获取方法匹配器
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
// 方法匹配
match = mm.matches(method, actualClass);
}
// 方法匹配通过
if (match) {
// 把通知适配成MethodInterceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 方法匹配器是运行时的(执行时去确定走不走代理)
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
// 创建一个InterceptorAndDynamicMethodMatcher
// 把所有拦截器拦截器和方法匹配器传入
// 方法匹配器有两个个方法,第二个是和入参相关的所以放到后续去判断
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
// 方法匹配器属性是静态直接添加到拦截链中
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
// endregion
// region IntroductionAdvisor类型切面
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
// endregion
// region 其它类型切面
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
// endregion
}
return interceptorList;
}
适配方法拦截器
public DefaultAdvisorAdapterRegistry() {
// 方法前置适配器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
// 方法后置适配器
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
// 异常适配器
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
// MethodInterceptor类型直接添加
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
// 需要被适配的通,默认就是三种:前置,后置,异常
for (AdvisorAdapter adapter : this.adapters) {
// 判断支不支持,上面三种就是判断通知类型是不是MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice
if (adapter.supportsAdvice(advice)) {
// 添加到方法拦截器集合
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
拿其中一种举例
了解完aop原理,下节我会解析基于Spring动态代理实现的一些功能
业务中的AspectJ中的@Aspect,@Before,@Around,@After 注解的任何实现
事务的底层逻辑
@Lazy懒加载如何实现
本文暂时没有评论,来添加一个吧(●'◡'●)