前言 上一篇 中我们扒拉了一下spring-aop
的底裤,详细解读了spring-aop
中的各种抽象概念,本篇开始我们一起研究研究spring-aop
的织入过程(基于5.2.6.RELEASE
)。建议各位同学本地打开一份源码对照食用,效果更佳。
前方高能!!!本篇重度依赖于上一篇解读的抽象概念,不熟悉的同学请速速撤离,以免误伤。
正式开始之前,各位同学还请思考一下,在拥有了关于AOP的全局视角之后,如果是你,会怎样有机地结合这些概念来实现织入呢?我听到有同学说利用BeanPostProcessor
。嗯,不错,Bean后置处理器给我们提供了这样一个切入点——可以在Bean自动装配完毕、行将可用之前对它进行定制,如果我们在这里返回一个代理对象,那么它就会取代原始对象。具体来说,就是在BeanPostProcessor#postProcessAfterInitialization(...)
回调中完成织入并返回新创建的代理对象。那么,真的是这样吗?
一切从EnableAspectJAutoProxy说起 EnableAspectJAutoProxy
的作用自不必多说,不过我们今天深入一点,探究一下它的源码。这个说白了就是看它通过Import
元注解向容器中导入了些什么,我们知道Spring中EnableXXX
类型的注解都是代理给Import
元注解向容器中导入功能组件的。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import({AspectJAutoProxyRegistrar.class}) public @interface EnableAspectJAutoProxy { boolean proxyTargetClass () default false ; boolean exposeProxy () default false ; }
注意到注解中的两个属性也存在于Advised
接口,而Advised
又保存着AOP配置信息,因此我们可以大胆地猜测这两个属性值最终会同步给Advised
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions (AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy != null ) { if (enableAspectJAutoProxy.getBoolean("proxyTargetClass" )) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy" )) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } }
AspectJAutoProxyRegistrar
做的事情非常简单:
向容器中导入一个AnnotationAwareAspectJAutoProxyCreator
类型的Bean,并设置优先级和角色
同步EnableAspectJAutoProxy
注解的属性值给它
那么问题来了,这个AnnotationAwareAspectJAutoProxyCreator
是个什么鬼呢?看名字的话它是某种自动代理的创建器,那么是不是就是它实现了BeanPostProcessor
接口呢?
Variant AutoProxyCreator Hierarchy of AnnotationAwareAspectJAutoProxyCreator
查看类图,结果确如我们所想,AnnotationAwareAspectJAutoProxyCreator
实现了BeanPostProcessor
接口,只不过是其父类实现的。好呗,扒就扒到底,AbstractAutoProxyCreator
走起。
What is SmartInstantiationAwareBeanPostProcessor 题外话,AbstractAutoProxyCreator
实现的并不是普通的BeanPostProcessor
,而是SmartInstantiationAwareBeanPostProcessor
。有些同学可能不太熟悉这个接口,简单说明一下,我们先看它的父接口InstantiationAwareBeanPostProcessor
。
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 public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { @Nullable default Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) throws BeansException { return null ; } default boolean postProcessAfterInstantiation (Object bean, String beanName) throws BeansException { return true ; } @Nullable default PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) throws BeansException { return null ; } @Deprecated @Nullable default PropertyValues postProcessPropertyValues (PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; } }
spring-context
中,CommonAnnotationBeanPostProcessor
就实现了InstantiationAwareBeanPostProcessor
接口用以支持javax.annotation.Resource
注解。接下来是SmartInstantiationAwareBeanPostProcessor
。
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 public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { @Nullable default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException { return null ; } @Nullable default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException { return null ; } default Object getEarlyBeanReference (Object bean, String beanName) throws BeansException { return bean; } }
AbstractAutoProxyCreator是如何执行织入的 Implementing SmartInstantiationAwareBeanPostProcessor 好了,言归正题,回到AbstractAutoProxyCreator
,挑出它对SmartInstantiationAwareBeanPostProcessor
的实现部分。
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 @Override @Nullable public Class<?> predictBeanType(Class<?> beanClass, String beanName) { if (this .proxyTypes.isEmpty()) { return null ; } Object cacheKey = getCacheKey(beanClass, beanName); return this .proxyTypes.get(cacheKey); }@Override public Object getEarlyBeanReference (Object bean, String beanName) { Object cacheKey = getCacheKey(bean.getClass(), beanName); this .earlyProxyReferences.put(cacheKey, bean); return wrapIfNecessary(bean, beanName, cacheKey); }@Override public Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this .targetSourcedBeans.contains(beanName)) { if (this .advisedBeans.containsKey(cacheKey)) { return null ; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this .advisedBeans.put(cacheKey, Boolean.FALSE); return null ; } } TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null ) { if (StringUtils.hasLength(beanName)) { this .targetSourcedBeans.add(beanName); } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this .proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } return null ; }@Override public Object postProcessAfterInitialization (@Nullable Object bean, String beanName) { if (bean != null ) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this .earlyProxyReferences.remove(cacheKey) != bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
如果不考虑自定义TargetSourceCreator
这种非常规流程,AbstractAutoProxyCreator
一共有两个机会来完成织入,一处在getEarlyBeanReference(...)
,另一处在postProcessAfterInitialization(...)
。这两处都调用了wrapIfNecessary(...)
来完成最后的织入,继续往下看。
wrapIfNecessary 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 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; }
wrapIfNecessary(...)
和postProcessBeforeInstantiation(...)
做的事情差不多,核心逻辑其实只有两步:
获取可以作用在目标对象上的Advisor
集合
将第1步获取到的Advisor list
转换成Interceptor list
并安装到Join point
上,说人话就是创建代理对象
createProxy(...)
整个流程比较复杂,涉及到Advice
的适配和扩展、拦截器链的初始化和安装、代理的创建等等,我们下篇再说。getAdvicesAndAdvisorsForBean(...)
是一个模板方法,实现它的是AbstractAutoProxyCreator
的子类AbstractAdvisorAutoProxyCreator
,接下来我们分析一下getAdvicesAndAdvisorsForBean(...)
。
AbstractAdvisorAutoProxyCreator是如何筛选Advisor的 getAdvicesAndAdvisorsForBean 1 2 3 4 5 6 7 8 9 10 @Override @Nullable 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(); }
可以看到,它代理给了findEligibleAdvisors(...)
,继续跟踪。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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; }
findEligibleAdvisors(...)
的流程还是比较清晰的:
找出容器中所有的Advisor
通过Pointcut进行筛选
对剩下的Advisor进行排序
findCandidateAdvisors 1 2 3 4 protected List<Advisor> findCandidateAdvisors () { Assert.state(this .advisorRetrievalHelper != null , "No BeanFactoryAdvisorRetrievalHelper available" ); return this .advisorRetrievalHelper.findAdvisorBeans(); }
发现它又代理给了advisorRetrievalHelper#findAdvisorBeans()
。
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 List<Advisor> findAdvisorBeans () { String[] advisorNames = this .cachedAdvisorBeanNames; if (advisorNames == null ) { advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this .beanFactory, Advisor.class, true , false ); this .cachedAdvisorBeanNames = advisorNames; } if (advisorNames.length == 0 ) { return new ArrayList<>(); } List<Advisor> advisors = new ArrayList<>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this .beanFactory.isCurrentlyInCreation(name)) { if (logger.isTraceEnabled()) { logger.trace("Skipping currently created advisor '" + name + "'" ); } } else { try { advisors.add(this .beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; String bceBeanName = bce.getBeanName(); if (bceBeanName != null && this .beanFactory.isCurrentlyInCreation(bceBeanName)) { if (logger.isTraceEnabled()) { logger.trace("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } continue ; } } throw ex; } } } } return advisors; }
findAdvisorsThatCanApply 1 2 3 4 5 6 7 8 9 10 11 12 protected List<Advisor> findAdvisorsThatCanApply ( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null ); } }
核心逻辑都在AopUtils
中了。
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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 public static List<Advisor> findAdvisorsThatCanApply (List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { continue ; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }public static boolean canApply (Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { return true ; } } public static boolean canApply (Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null" ); if (!pc.getClassFilter().matches(targetClass)) { return false ; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { return true ; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null ; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if (introductionAwareMethodMatcher != null ? introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true ; } } } return false ; }
sortAdvisors 1 2 3 4 protected List<Advisor> sortAdvisors (List<Advisor> advisors) { AnnotationAwareOrderComparator.sort(advisors); return advisors; }
默认的排序策略是很简单的,根据Advisor
实现的Ordered
接口或标注的Order
注解提供的优先级进行排序。
结语 本篇我们从EnableAspectJAutoProxy
注解着手,一步一步分析了spring-aop
是如何通过BeanPostProcessor
来执行织入的,下一篇我们一起看看创建动态代理的全流程吧~~