spring-framework 版本:v5.3.19
文章目录
- 1、ProxyFactory
- 1.1、createAopProxy() 创建AopProxy
- 1.2、getProxy() 创建代理对象
- 1.3、JdkDynamicAopProxy#invoke 代理逻辑
- 1.3.1、advised.getInterceptorsAndDynamicInterceptionAdvice() 匹配添加的advisor并转化成所需对象
- 1.3.2、invocation.proceed() 执行代理逻辑
- 2、DefaultAdvisorAutoProxyCreator
- 3、AnnotationAwareAspectJAutoProxyCreator
废话少说,上代码
在spring-aop中,无论是xml还是注解还是硬编码配置的代理,最后都会通过proxyFactory去实现真正的代理。
proxyFactory的使用也很简单,给他一个target和一个advisor即可生成代理类。
target就是被代理对象,而 advisor 可以简单的理解成 advice + pointcut
1、ProxyFactory
所以proxyFctory是如何生成代理对象的?
追踪ProxyFactory.getProxy()方法
1.1、createAopProxy() 创建AopProxy
这里可能创建 CglibAopProxy 也可能创建 JdkDynamicAopProxy,分别对应两种不同的动态代理方式
AopProxy 由 AopProxyFactory生成,而spring默认的AopProxyFactory只有 DefaultAopProxyFactory 这一个实现。
通俗的说就是:如果目标对象至少实现了一个接口则使用jdk,反之使用cglib。同时也可配置 optimize = true 或者 proxyTargetClass = true 强制使用cglib代理。
1.2、getProxy() 创建代理对象
这里就是用cglib或者是jdk的方式去创建一个代理对象了。以jdk为例,其实就是我们平时使用jdk动态代理的代码。
JdkDynamicAopProxy.getProxy()
注意看 Proxy.newProxyInstance 的 InvocationHandler 传了this,说明 JdkDynamicAopProxy 同时也实现了 InvocationHandler 。
也就是最最最重要的代理逻辑就在 JdkDynamicAopProxy.invoke 方法。
1.3、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,hashCodeif (!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中// 当想要自己调自己同时代理不失效的时候可以配为trueif (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);//匹配添加的advisorList<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);}}}
1.3.1、advised.getInterceptorsAndDynamicInterceptionAdvice() 匹配添加的advisor并转化成所需对象
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 和 classif (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {//匹配 methodMethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {//如果MethodMatcher是IntroductionAwareMethodMatcher的话,则用IntroductionAwareMethodMatcher.matchesif (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {//反之直接用MethodMatcher.matchesmatch = mm.matches(method, actualClass);}if (match) {//如果匹配则将 advisor 转化成 MethodInterceptor[]MethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {// 如果runtime为true,说明需要根据参数动态匹配,添加 InterceptorAndDynamicMethodMatcherfor (MethodInterceptor interceptor : interceptors) {//InterceptorAndDynamicMethodMatcher = MethodInterceptor + MethodMatcherinterceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {// 反之直接加到listinterceptorList.addAll(Arrays.asList(interceptors));}}}}else if (advisor instanceof IntroductionAdvisor) {//IntroductionAdvisor分支IntroductionAdvisor ia = (IntroductionAdvisor) advisor;//匹配 prefiltered 和 classif (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {// 如果匹配 将advisor转成Interceptor[] 放到listInterceptor[] 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。
1.3.2、invocation.proceed() 执行代理逻辑
为空的情况没什么好说的直接反射调用就是了。
不为空的情况下,会将所有代理所需要的变量封装成一个 MethodInvocation ,并递归调用proceed()执行代理逻辑。
invocation.proceed()
以beforeAdvice转化的MethodBeforeAdviceInterceptor为例看一下是如何递归的。
至此,proxyFactory的jdk代理就看完了,cglib的代理也是类似的。无非就是生成代理对象时所用的技术不同而已,像什么advisor,AdvisorAdapter,methodInterceptor,InterceptorAndDynamicMethodMatcher,methodInvocation,等都是一样的。
总结上面的内容粗略画了一个流程图:
2、DefaultAdvisorAutoProxyCreator
不过我们平时使用spring-aop的时候貌似没有用到proxyFactory。而是只需配置advisor bean或者使用aspectj注解配置切面就可以了。
比如这样
为什么这里容器得到了bean会是一个代理类呢?什么时候给他代理了?
答案就在import的 DefaultAdvisorAutoProxyCreator。
DefaultAdvisorAutoProxyCreator 本质上是一个SmartInstantiationAwareBeanPostProcessor,即BeanPostProcessor。在容器启动的时候会增强bean,所谓的增强其实就是自动扫描容器中匹配的advisor,并代理目标bean。
postProcessAfterInitialization 方法的增强逻辑在其抽象父类AbstractAutoProxyCreator
3、AnnotationAwareAspectJAutoProxyCreator
而 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自定义自动代理创建逻辑。