曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】) (3)

根据bean definition来实例化,假设bean class为A,bean definition中的constructorArgumentValues参数,如果为空,则使用A的默认构造函数;如果constructorArgumentValues有值,表示:在此之前,需要先获取到相应的构造函数值,才能去反射通过构造器来创建对象

这里面,会涉及到bean的递归调用。

比如,以前一篇和开头提到的,AspectJPointcutAdvisor 这个bean definition来说,其中它的构造函数,就要求一个AbstractAspectJAdvice 对象:

public AspectJPointcutAdvisor(AbstractAspectJAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; this.pointcut = advice.buildSafePointcut(); }

那AbstractAspectJAdvice 这个对象要怎么生成,这个在我们的场景下,是被抽象成一个内部bean的,bean class为AspectJAfterAdvice。AspectJAfterAdvice这个类呢,构造函数又是下面这样的:

public AspectJAfterAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); }

又依赖了一堆其他的参数,这三个参数,其中2个也是被定义为了内部bean definition,一个为bean 引用。(具体请参照前一篇)。

所以,这个bean的实例化过程就相对繁琐,涉及到bean的递归生成。

InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation;

属性注入,此时是autowired等发挥作用的地方;

BeanPostProcessor的postProcessBeforeInitialization

BeanPostProcessor#postProcessAfterInitialization

这里面6个步骤,AspectJAwareAdvisorAutoProxyCreator 在其中两个地方,实现了自己的业务逻辑。

2.1 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation

具体实现在:

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } // 入口在这:shouldSkip if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { 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; }

以上逻辑中,我们需要进入到shouldSkip方法,重点是下面的findCandidateAdvisors方法:

@Override protected boolean shouldSkip(Class beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names /** * 这里调用了父类中实现的findCandidateAdvisors,获取候选的advisor bean;这里也是真正根据bean * definition去生成advisor bean的地方 */ List<Advisor> candidateAdvisors = **findCandidateAdvisors()**; for (Advisor advisor : candidateAdvisors) { /** * 如果当前要检查的bean,就是advisor里的通知类,则跳过 */ if (advisor instanceof AspectJPointcutAdvisor) { if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { return true; } } } return super.shouldSkip(beanClass, beanName); }

下面会找出ioc容器中,实现了Advisor接口的bean definition,并全部实例化。Advisor是什么?

我们前面提到的AspectJPointcutAdvisor,就实现了这个接口。

public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // 1.从spring容器查找Advisor类型的bean definition advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name) && !this.beanFactory.isCurrentlyInCreation(name)) { // 遍历那些bean definition,通过getBean,来获取bean advisors.add(this.beanFactory.getBean(name, Advisor.class)); } } return advisors; }

曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)

再啰嗦一句,advisor差不多是aop的核心数据结构,你通过Aspect注解方式,最终也是解析为一个个的Advisor。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zypydw.html