|
1. 从注解入手找到对应核心类 最近工作中我都是基于注解实现AOP功能,常用的开启AOP的注解是@EnableAspectJAutoProxy,我们就从它入手。

上面的动图的流程的步骤就是: @EnableAspectJAutoProxy --> AspectJAutoProxyRegistrar -->AopConfigUtils .registerAspectJAnnotationAutoProxyCreatorIfNecessary -->AnnotationAwareAspectJAutoProxyCreator.class


虽然找到了核心类,但是并没有找到核心方法!下面我们尝试画类图确定核心方法。 2.画核心类类图,猜测核心方法 AnnotationAwareAspectJAutoProxyCreator的部分类图。

从类图看到了AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,而AOP功能应该在创建完Bean之后执行,猜测AnnotationAwareAspectJAutoProxyCreator实现BeanPostProcessor的postProcessAfterInitialization(实例化bean后处理)是核心方法。 查看AnnotationAwareAspectJAutoProxyCreator实现的postProcessAfterInitialization方法,实际该方法在其父类AbstractAutoProxyCreator中。

发现发现疑似方法wrapIfNecessary,查看其源码如下,发现createProxy方法。确定找对了地方。

即AnnotationAwareAspectJAutoProxyCreator实现BeanPostProcessor的postProcessAfterInitialization方法,在该方法中由wrapIfNecessary实现了AOP的功能。 wrapIfNecessary中有2个和核心方法 getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器 createProxy为当前bean创建代理 要想明白核心流程还需要分析这2个方法。 3.读重点方法,理核心流程 3.1 getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器 查看源码如下,默认实现在AbstractAdvisorAutoProxyCreator中。

查阅findEligibleAdvisors方法,就干了3件事 找所有增强器,也就是所有@Aspect注解的Bean 找匹配的增强器,也就是根据@Before,@After等注解上的表达式,与当前bean进行匹配,暴露匹配上的。 对匹配的增强器进行扩展和排序,就是按照@Order或者PriorityOrdered的getOrder的数据值进行排序,越小的越靠前。

AnnotationAwareAspectJAutoProxyCreator 重写了findCandidateAdvisors,下面我们看看具体实现了什么 3.1.1findCandidateAdvisors找所有增强器,也就是所有@Aspect注解的Bean

从该方法我们可以看到处理@Aspect注解的bean的方法是:this.aspectJAdvisorsBuilder.buildAspectJAdvisors()。 这个方法如下: public List<Advisor> buildAspectJAdvisors() { ? List<String> aspectNames = this.aspectBeanNames; ? if (aspectNames == null) { ? ? ? synchronized (this) { ? ? ? ? aspectNames = this.aspectBeanNames; ? ? ? ? if (aspectNames == null) { ? ? ? ? ? ? List<Advisor> advisors = new ArrayList<>(); ? ? ? ? ? ? aspectNames = new ArrayList<>(); ? ? ? ? ? ? //找到所有BeanName? ? ? ? ? ? String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( ? ? ? ? ? ? ? ? ? this.beanFactory, Object.class, true, false); ? ? ? ? ? ? for (String beanName : beanNames) { ? ? ? ? ? ? ? if (!isEligibleBean(beanName)) { ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? } ? ? ? ? ? ? ? // 必须注意,bean会提前暴露,并被Spring容器缓存,但是这时还不能织入。? ? ? ? ? ? ? Class<?> beanType = this.beanFactory.getType(beanName); ? ? ? ? ? ? ? if (beanType == null) { ? ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? ? } ? ? ? ? ? ? ? if (this.advisorFactory.isAspect(beanType)) { ? ? ? ? ? ? ? ? ? //找到所有被@Aspect注解的类? ? ? ? ? ? ? ? ? aspectNames.add(beanName); ? ? ? ? ? ? ? ? ? AspectMetadata amd = new AspectMetadata(beanType, beanName); ? ? ? ? ? ? ? ? ? if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { ? ? ? ? ? ? ? ? ? ? MetadataAwareAspectInstanceFactory factory = ? ? ? ? ? ? ? ? ? ? ? ? ? new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); ? ? ? ? ? ? ? ? ? ? //解析封装为Advisor返回? ? ? ? ? ? ? ? ? ? List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); ? ? ? ? ? ? ? ? ? ? if (this.beanFactory.isSingleton(beanName)) { ? ? ? ? ? ? ? ? ? ? ? ? this.advisorsCache.put(beanName, classAdvisors); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? else { ? ? ? ? ? ? ? ? ? ? ? ? this.aspectFactoryCache.put(beanName, factory); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? advisors.addAll(classAdvisors); ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? else { ? ? ? ? ? ? ? ? ? ? // Per target or per this.? ? ? ? ? ? ? ? ? ? if (this.beanFactory.isSingleton(beanName)) { ? ? ? ? ? ? ? ? ? ? ? ? throw new IllegalArgumentException("Bean with name '" + beanName + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "' is a singleton, but aspect instantiation model is not singleton"); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? MetadataAwareAspectInstanceFactory factory = ? ? ? ? ? ? ? ? ? ? ? ? ? new PrototypeAspectInstanceFactory(this.beanFactory, beanName); ? ? ? ? ? ? ? ? ? ? this.aspectFactoryCache.put(beanName, factory); ? ? ? ? ? ? ? ? ? ? advisors.addAll(this.advisorFactory.getAdvisors(factory)); ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? ? ? this.aspectBeanNames = aspectNames; ? ? ? ? ? ? return advisors; ? ? ? ? } ? ? ? } ? } ? if (aspectNames.isEmpty()) { ? ? ? return Collections.emptyList(); ? } ? List<Advisor> advisors = new ArrayList<>(); ? for (String aspectName : aspectNames) { ? ? ? List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); ? ? ? if (cachedAdvisors != null) { ? ? ? ? advisors.addAll(cachedAdvisors); ? ? ? } ? ? ? else { ? ? ? ? MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); ? ? ? ? advisors.addAll(this.advisorFactory.getAdvisors(factory)); ? ? ? } ? } ? return advisors; } 这个方法可以概括为: 找到所有BeanName 根据BeanName筛选出被@Aspect注解的类 针对类中被Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class注解的方法,先按上边的注解顺序排序后按方法名称排序,每一个方法对应一个Advisor。 3.2 createProxy为当前bean创建代理。 3.2.1 创建代理的2种方式 众所周知,创建代理的常用的2种方式是:JDK创建和CGLIB,下面我们就看看这2中创建代理的例子。 3.2.1 .1 jdk创建代理的例子

3.2.1 .2 cglib创建代理的例子

3.2.1 .3 jdk创建代理与cglib创建代理的区别

3.2.2 Spring如何选择的使用哪种方式 Spring的选择选择如何代理时在DefaultAopProxyFactory 中。

config.isOptimize() 查看源码注释时发现,这个是配置使用cglib代理时,是否使用积极策略。这个值一般不建议使用! config.isProxyTargetClass() 就是@EnableAspectJAutoProxy中的proxyTargetClass属性。

hasNoUserSuppliedProxyInterfaces 是否存在可代理的接口 总结下Spring如何选择创建代理的方式: 如果设置了proxyTargetClass=true,一定是CGLIB代理 如果proxyTargetClass=false,目标对象实现了接口,走JDK代理 如果没有实现接口,走CGLIB代理
4.总结 Spring如何实现AOP?,
您可以这样说: AnnotationAwareAspectJAutoProxyCreator是AOP核心处理类
AnnotationAwareAspectJAutoProxyCreator实现了BeanProcessor,其中postProcessAfterInitialization是核心方法。
核心实现分为2步
getAdvicesAndAdvisorsForBean获取当前bean匹配的增强器
createProxy为当前bean创建代理
getAdvicesAndAdvisorsForBean核心逻辑如下
a. 找所有增强器,也就是所有@Aspect注解的Bean
b. 找匹配的增强器,也就是根据@Before,@After等注解上的表达式,与当前bean进行匹配,暴露匹配上的。
c. 对匹配的增强器进行扩展和排序,就是按照@Order或者PriorityOrdered的getOrder的数据值进行排序,越小的越靠前。
createProxy有2种创建方法,JDK代理或CGLIB
a. 如果设置了proxyTargetClass=true,一定是CGLIB代理
b. 如果proxyTargetClass=false,目标对象实现了接口,走JDK代理
c. 如果没有实现接口,走CGLIB代理
----------------------------
原文链接:https://www.jianshu.com/p/12de4336d431
程序猿的技术大观园:www.javathinker.net
|
|