在Spring AOP源码(二):BeanDefinition的准备工作中,介绍了Spring准备AOP相关的BeanDefinition对象,同样的对于普通的bean对象的创建此处不再赘述,主要分析动态代理创建器、Advisor是如何实例化的。
1、动态代理模式创建器实例化
在上一篇中已经知道Spring中AOP的自动代理模式创建器AnnotationAwareAspectJAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,同时也实现了Ordered接口。
在IOC容器创建的过程中,registerBeanPostProcessors(beanFactory)是对容器中BeanPostProcessor做处理的方法,核心流程:PostProcessorRegistrationDelegate#registerBeanPostProcessors核心伪代码如下:
1 // 注册并实例化AOP的动态代理 2 public static void registerBeanPostProcessors( 3 ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { 4 5 // 找到所有实现了BeanPostProcessor接口的类 6 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); 7 // ...... 8 // 定义存放实现了Ordered接口的BeanPostProcessor的name集合 9 List<String> orderedPostProcessorNames = new ArrayList<>(); 10 // ...... 11 // 注册所有实现Ordered的beanPostProcessor 12 List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); 13 for (String ppName : orderedPostProcessorNames) { 14 // 根据ppName找到对应的BeanPostProcessor实例对象 15 BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 16 // 将实现了Ordered接口的BeanPostProcessor添加到orderedPostProcessors集合中 17 orderedPostProcessors.add(pp); 18 } 19 // 注册实现了Ordered接口的BeanPostProcessor实例添加到beanFactory中 20 registerBeanPostProcessors(beanFactory, orderedPostProcessors); 21 // ...... 22 }
有一点需要注意,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口,这个在将BeanPostProcessor注册到beanPostProcessors容器中时,会将AbstractBeanFactory属性hasInstantiationAwareBeanPostProcessors实例化后置处理器注册标识设置为true。
AbstractBeanFactory#addBeanPostProcessor核心伪代码如下:
1 // 将BeanPostProcessor注册到beanPostProcessors容器中 2 public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { 3 4 // 如果beanPostProcessors集合中已经存在此beanPostProcessors对象,移除该对象 5 this.beanPostProcessors.remove(beanPostProcessor); 6 7 // beanPostProcessor是为InstantiationAwareBeanPostProcessor类型,Bean对象实例化后置处理器注册标识设置为true 8 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { 9 this.hasInstantiationAwareBeanPostProcessors = true; 10 } 11 12 // 将beanPostProcessor加入后置处理器集合中 13 this.beanPostProcessors.add(beanPostProcessor); 14 }
hasInstantiationAwareBeanPostProcessors标识在后续的Advisor实例化中会用到,这里先记住这个结论。
2、Advisor的实例化
2.1、AOP常用五大通知Advice的类图
1、前置通知 AspectJMethodBeforeAdvice
2、后置通知 AspectJAfterAdvice
3、环绕通知 AspectJAroundAdvice
4、后置返回通知 AspectJAfterReturningAdvice
5、后置异常通知 AspectAfterThrowingAdvice
6、结论
通过AOP常用的五大Advice的类图发现,AOP的Advice没有实现BeanFactoryPostProcessor、BeanPostProcessor接口,所以Advisor与普通的bean实例化、初始化一样,在IOC容器启动过程中,finishBeanFactoryInitialization(beanFactory)方法是完成容器中普通bean实例化的方法。2.2、Advisor的实例化
1、Advisor实例化的时机
有个问题需要我们思考,Advisior是在哪个步骤做实例化的呢,我们先看下Bean的生命周期:
1、bean实例化前的处理 2、bean的实例化 class.newInstance() 3、bean初始化前的处理 4、bean初始化 5、bean初始化后的处理 6、bean的销毁 Spring是在哪个周期来实现Advisor实例化的呢?2、Advisor创建的核心流程
由此上面的流程可知,在aop切面aspect的普通bean标签的实例化时,在实例化之前,查找beanFactory容器中所有实现Advisor的beanDefinition并做实例化操作,并将遍历Advisor集合,如果Advisor集合中的存在某个Advisor切面的AspectName与正在创建的beanName相同,则跳过resolveBeforeInstantiation处理。
AspectJAwareAdvisorAutoProxyCreator#shouldSkip 查找并实例化Advisor入口核心代码:1 // 是否应该跳过 2 protected boolean shouldSkip(Class<?> beanClass, String beanName) { 3 // 查找并创建容器中所以的Advisor 4 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 5 // 遍历Advisor集合 6 for (Advisor advisor : candidateAdvisors) { 7 // Advisor是AspectJPointcutAdvisor类型并且Advisor中的切面与正在创建的beanName相同 8 if (advisor instanceof AspectJPointcutAdvisor && 9 ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) { 10 return true; 11 } 12 } 13 return super.shouldSkip(beanClass, beanName); 14 }
AbstractAdvisorAutoProxyCreator#findAdvisorBeans 查找并实例化Advisor的核心伪代码:
1 // 查找容器中所有的Advisor对象 2 public List<Advisor> findAdvisorBeans() { 3 // 获取已经缓存的Advisor的beanName集合 4 String[] advisorNames = this.cachedAdvisorBeanNames; 5 6 if (advisorNames == null) { 7 // 获取当前BeanFactory中所有实现了Advisor接口的bean的名称 8 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( 9 this.beanFactory, Advisor.class, true, false); 10 this.cachedAdvisorBeanNames = advisorNames; 11 } 12 13 if (advisorNames.length == 0) { 14 return new ArrayList<>(); 15 } 16 17 // 对获取到的实现Advisor接口的bean的名称进行遍历 18 List<Advisor> advisors = new ArrayList<>(); 19 // 循环所有的beanName,找出对应的增强方法 20 for (String name : advisorNames) { 21 // 创建Advisor, 并将当前bean添加到Advisor集合中,用于后续遍历 22 advisors.add(this.beanFactory.getBean(name, Advisor.class)); 23 } 24 return advisors; 25 }
getBean -> doGetBean -> CreateBean -> doCreateBean,此处便是创建Advisor的bean的地方。
到这里,就可以回答Advisor实例化的时机了,在创建配置文件中的首个bean标签时,在实例化之前会对判断是否提前生成代理对象,在shouldSkip中查询容器中所有实现Advisor的beanName,并通过getBean创建AOP的Advisor对象。3、Advisor实例化步骤
3.1、Advisor的有参构造函数
Spring中,一般bean都是调用无参构造函数,通过反射class.newInstance()来完成实例化的。但是Advisor没有无参构造函数,只有参构造函数,构造函数详情。1 // 为给定的Advice创建一个AspectJPointcutAdvisor实例 2 public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) { 3 Assert.notNull(advice, "Advice must not be null"); 4 this.advice = advice; 5 this.pointcut = advice.buildSafePointcut(); 6 }
3.2、Advice的有参构造函数
通过AOP常用五大通知Advice的类图可知,AbstractAspectJAdvice是AOP五大通知的父类,我们看下具体的Advice的构造函数 AspectJAfterAdvice - 后置通知的有参构造函数1 public AspectJAfterAdvice( 2 Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { 3 4 super(aspectJBeforeAdviceMethod, pointcut, aif); 5 }AspectJMethodBeforeAdvice - 前置通知的有参构造函数
1 public AspectJMethodBeforeAdvice( 2 Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { 3 4 super(aspectJBeforeAdviceMethod, pointcut, aif); 5 }
AspectJAroundAdvice - 环绕通知的有参构造函数
1 public AspectJAroundAdvice( 2 Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { 3 4 super(aspectJAroundAdviceMethod, pointcut, aif); 5 }
AspectJAfterReturningAdvice - 后置返回通知的有参构造函数
1 public AspectJAfterReturningAdvice( 2 Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { 3 4 super(aspectJBeforeAdviceMethod, pointcut, aif); 5 }
AspectJAfterThrowingAdvice - 后置异常通知有参构造函数
1 public AspectJAfterThrowingAdvice( 2 Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { 3 4 super(aspectJBeforeAdviceMethod, pointcut, aif); 5 }
advisor的有参构造函数中,参数为Advice; Advice的有参构造函数中,参数为Method、AspectJExpressionPointcut、AspectInstanceFactory。要想实例化Advisor,必须先实例化Advice; 若要实例化Advice,必须先实例化Method、AspectJExpressionPointcut、AspectInstanceFactory,这个实例化过程是很麻烦的。
3.3、Advice有参构造函数中的参数实例
Advisor实例化的核心流程:
标签:BeanPostProcessor,实例,AOP,bean,Bean,源码,Advisor,构造函数 From: https://www.cnblogs.com/RunningSnails/p/17011205.html