前言 本文是看了田小波博主的Spring AOP源码分析系列 后自己总结整理的笔记,内容会更偏向于流程上的总结,具体源码细节并未深入研究,并且关于AOP的相关术语这里也不会再说明。
大致流程 本文将会从AOP的入口开始分析,主要涉及以下四个流程:
入口分析
筛选合适的通知器
创建代理对象
拦截器链的执行过程
入口分析 Spring是通过后置处理器BeanPostProcessor
接口在init-method
的前后通过切点对bean类中的方法进行匹配后织入的,这个接口是Spring提供的一个扩展接口,通过实现该接口,用户可在Bean初始化前后做一些自定义的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 protected Object initializeBean (final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null ), beanName, "Invocation of init method failed" , ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
Spring AOP抽象代理创建器AbstractAutoProxyCreator
实现了BeanPostProcessor
接口,并在Bean初始化后置处理过程中向Bean织入通知:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor , BeanFactoryAware { @Override public Object postProcessBeforeInitialization (Object bean, String beanName) { return bean; } @Override public Object postProcessAfterInitialization (@Nullable Object bean, String beanName) throws BeansException { if (bean != null ) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this .earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary (Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this .targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this .advisedBeans.get(cacheKey))) { return bean; } if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this .advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null ); if (specificInterceptors != DO_NOT_PROXY) { this .advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this .proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this .advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } }
可以看出,postProcessAfterInitialization
主要过程分为四步:
若Bean是AOP基础设施类型(Pointcut、Advice、Advisor 等接口的实现类),则直接返回
为目标Bean查找匹配的通知器(通知器持有通知)
如果找到了匹配的通知器,则为Bean生成代理对象,并返回该对象
否则,返回原始bean
筛选合适的通知器 上文说过,在创建代理对象前,首先要查找合适的通知器Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
,这一行代码对应着postProcessAfterInitialization
的第二步,具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors (Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
该过程首先会查询出所有的通知器,然后再通过ClassFilter
和MethodMatcher
对目标类和方法进行匹配,筛选出可应用到当前bean的通知器。下面分析查询出所有的通知器的过程。
查找所有通知器 这个方法在子类AnnotationAwareAspectJAutoProxyCreator
中被覆写过,增加了对@Aspect
注解的解析:
1 2 3 4 5 6 7 8 9 10 @Override protected List<Advisor> findCandidateAdvisors () { List<Advisor> advisors = super .findCandidateAdvisors(); if (this .aspectJAdvisorsBuilder != null ) { advisors.addAll(this .aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
这两行代码分别做了两件事:
第一步从容器中获取所有类型为Advisor
的bean
第二步获取容器中所有beanName以及每个beanName对应的bean类型,遍历判断当前bean是否是一个Aspect注解类,若是则调用advisorFactory.getAdvisors
获取所有通知器列表,其中会为每个方法调用getAdvisor
方法,这个方法会获取AspectJ表达式切点(也就是获取方法上的相关注解如@Before
、@After
等并创建一个AspectJExpressionPointcut
对象),并且创建Advisor
实现类(这其中会先根据注解类型创建相应的通知Advice
实现类)。
创建代理对象 当Bean实现了接口时,Spring会基于JDK动态代理为目标Bean创建代理对象,若未实现任何接口,Spring则会通过CGLIB创建代理,而当proxy-target-class
属性设为true
时,则会强制Spring通过CGLIB的方式创建代理对象,即使目标Bean实现了接口。
AopProxy 为目标Bean创建代理对象前,需要先创建AopProxy
对象,然后再调用该对象的getProxy
方法创建实际的代理类:
1 2 3 4 5 public interface AopProxy { Object getProxy () ; Object getProxy (@Nullable ClassLoader classLoader) ; }
在Spring中,有两个类实现了AopProxy
,一个是CglibAopProxy
,另一个是JdkDynamicAopProxy
。在postProcessAfterInitialization
的第三步Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
会根据bean是否实现接口以及一些其它配置来决定使用AopProxy
的哪一个实现类为目标bean创建代理对象。
拦截器链的执行过程 在上面两个步骤中,Spring AOP已经为目标bean筛选出合适的通知器,创建好了代理对象,接下来就是要执行通知逻辑了。通知可能在目标方法前执行,也可能在目标方法后执行,当目标方法被多个通知匹配到时,Spring通过引入拦截器链来保证每个通知的正常执行。
JDK动态代理逻辑分析 对于JDK动态代理,代理逻辑封装在InvocationHandler
接口实现类的invoke
中,而JdkDynamicAopProxy
实现了InvocationHandler
接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 final class JdkDynamicAopProxy implements AopProxy , InvocationHandler , Serializable { @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation; Object oldProxy = null ; boolean setProxyContext = false ; TargetSource targetSource = this .advised.targetSource; Object target = null ; try { Object retVal; if (this .advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true ; } target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null ); List<Object> chain = this .advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); if (chain.isEmpty()) { Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed(); } return retVal; } finally { } } }
该方法的主要流程如下:
获取适合当前方法的拦截器(将advisor中的advice转成相应的拦截器)
如果拦截器链为空,则直接通过反射执行目标方法
否则,创建方法调用器ReflectiveMethodInvocation
对象,将拦截器链传入其中
调用ReflectiveMethodInvocation
对象的proceed()
方法启动拦截器链
处理返回值,并返回该值
其中,启动拦截器是核心步骤,ReflectiveMethodInvocation
的proceed
方法用于启动拦截器链,这里直接引用一副图很好的解释了拦截器链的执行过程:
由上图可以看出,方法调用器每次调用下一个拦截器的invoke
方法时,都会将自己作为参数传给该方法,并且通过方法调用器不断调用下一个拦截器,直到拦截器链中的最后一个拦截器执行完后,通过反射的方式执行目标方法,然后再返回到后置拦截器的方法中执行后置拦截器的一些逻辑。