spring-framework 版本:v5.3.19
废话少说,上代码
在spring-aop中,无论是xml还是注解还是硬编码配置的代理,最后都会通过proxyFactory去实现真正的代理。
proxyFactory的使用也很简单,给他一个target和一个advisor即可生成代理类。
target就是被代理对象,而 advisor 可以简单的理解成 advice + pointcut
所以proxyFctory是如何生成代理对象的?
这里可能创建 CglibAopProxy 也可能创建 JdkDynamicAopProxy,分别对应两种不同的动态代理方式
AopProxy 由 AopProxyFactory生成,而spring默认的AopProxyFactory只有 DefaultAopProxyFactory 这一个实现。
通俗的说就是:如果目标对象至少实现了一个接口则使用jdk,反之使用cglib。同时也可配置 optimize = true 或者 proxyTargetClass = true 强制使用cglib代理。
这里就是用cglib或者是jdk的方式去创建一个代理对象了。以jdk为例,其实就是我们平时使用jdk动态代理的代码。
JdkDynamicAopProxy.getProxy()
注意看 Proxy.newProxyInstance 的 InvocationHandler 传了this,说明 JdkDynamicAopProxy 同时也实现了 InvocationHandler 。
也就是最最最重要的代理逻辑就在 JdkDynamicAopProxy.invoke 方法。
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 {
//特殊方法以及对代理对象的配置信息进行操作,如不代理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) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//如果配置 exposeProxy = true 则把当前代理对象放到线程ThreadLocalMap中
// 当想要自己调自己同时代理不失效的时候可以配为true
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//匹配添加的advisor
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())) {
//特殊情况:当返回自身时,则返回代理后的对象
retVal = proxy;
}
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 {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
//分 PointcutAdvisor、IntroductionAdvisor、其他 三个分支
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
//PointcutAdvisor分支
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
//匹配 prefiltered 和 class
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//匹配 method
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
//如果MethodMatcher是IntroductionAwareMethodMatcher的话,则用IntroductionAwareMethodMatcher.matches
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
//反之直接用MethodMatcher.matches
match = mm.matches(method, actualClass);
}
if (match) {
//如果匹配则将 advisor 转化成 MethodInterceptor[]
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// 如果runtime为true,说明需要根据参数动态匹配,添加 InterceptorAndDynamicMethodMatcher
for (MethodInterceptor interceptor : interceptors) {
//InterceptorAndDynamicMethodMatcher = MethodInterceptor + MethodMatcher
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
// 反之直接加到list
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
//IntroductionAdvisor分支
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
//匹配 prefiltered 和 class
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
// 如果匹配 将advisor转成Interceptor[] 放到list
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
//其他类型的Advisor分支
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
至于是如何转化的,用了适配器模式。遍历所有 AdvisorAdapter,如果这个适配器可以转化,则进行转化。注意看,这里就算适配了也没有退出循环,也就是说一个advisor可能同时被多个适配器适配,这也就是为什么会返回数组的原因。
register.getInterceptors(advisor)
与其说转化advisor,我个人更喜欢理解成转化advice。
内置的适配器跟内置的advice是对应上的
以before为例
不过为什么没有环绕通知的适配器,因为我们用的AspectJAroundAdvice环绕通知本来就是一个MethodInterceptor
总之这一步会匹配符合的advisor并将其转化成所需对象(如MethodInterceptor)。匹配的逻辑根据advisor的类型分为三个分支:PointcutAdvisor、IntroductionAdvisor、其他,简单的说,他们的区别就是分别为匹配类和方法,匹配类,无需匹配直接添加。但无论是哪种分支,最终都会将advisor(直接或通过适配器)转化成 MethodInterceptor 或 InterceptorAndDynamicMethodMatcher。
为空的情况没什么好说的直接反射调用就是了。
不为空的情况下,会将所有代理所需要的变量封装成一个 MethodInvocation ,并递归调用proceed()执行代理逻辑。
invocation.proceed()
以beforeAdvice转化的MethodBeforeAdviceInterceptor为例看一下是如何递归的。
至此,proxyFactory的jdk代理就看完了,cglib的代理也是类似的。无非就是生成代理对象时所用的技术不同而已,像什么advisor,AdvisorAdapter,methodInterceptor,InterceptorAndDynamicMethodMatcher,methodInvocation,等都是一样的。
不过我们平时使用spring-aop的时候貌似没有用到proxyFactory。而是只需配置advisor bean或者使用aspectj注解配置切面就可以了。
比如这样
为什么这里容器得到了bean会是一个代理类呢?什么时候给他代理了?
答案就在import的 DefaultAdvisorAutoProxyCreator。
DefaultAdvisorAutoProxyCreator 本质上是一个SmartInstantiationAwareBeanPostProcessor,即BeanPostProcessor。在容器启动的时候会增强bean,所谓的增强其实就是自动扫描容器中匹配的advisor,并代理目标bean。
postProcessAfterInitialization 方法的增强逻辑在其抽象父类AbstractAutoProxyCreator
而 AnnotationAwareAspectJAutoProxyCreator 与 DefaultAdvisorAutoProxyCreator 最大的区别就在于寻找容器所有的advisor时,所使用的方法不同。 AnnotationAwareAspectJAutoProxyCreator 重写了findCandidateAdvisors() 使其支持将 aspectj 注解的内容转化成 advisor。
所以如果我们只是import了 DefaultAdvisorAutoProxyCreator 是不会去解析 aspectJ 对应的aop注解的。
只有当import了 AnnotationAwareAspectJAutoProxyCreator 才会去解析。这也正是 @EnableAspectJAutoProxy 注解所做的事情。
由代码也可以看出,当使用了 AnnotationAwareAspectJAutoProxyCreator 就没必要再使用 DefaultAdvisorAutoProxyCreator 了,因为前者不仅会解析 aspectJ 的注解生成advisor,同时也会像后者一样扫描当前已有的 advisor。
除了上面两种AutoProxyCreator,spring中还有 BeanNameAutoProxyCreator(根据bean name去自动创建),AspectJAwareAdvisorAutoProxyCreator(xml配置的aspectJ切面),InfrastructureAdvisorAutoProxyCreator(Infrastructure相关,如事务管理)。当然也可以自己去继承AbstractAdvisorAutoProxyCreator自定义自动代理创建逻辑。