欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

程序员文章站 2022-05-06 18:15:04
...

接上一篇spring aop源码解析1: 创建、初始化并注册AnnotationAwareAspectJAutoProxyCreator继续

现在我们在容器中已经有了AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor,那么之后我们再创建bean的时候,都会经过AnnotationAwareAspectJAutoProxyCreator这个后置处理器

接下来看这个后置处理器能干什么

AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessor

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

 

由于流程比较复杂,还是先上一张流程图

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

 

4.完成其余BeanFactory的初始化工作

在refresh方法中 注册好了BeanPostProcessor之后,执行finishBeanFactoryInitialization方法

org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

// Instantiate all remaining (non-lazy-init) singletons.

finishBeanFactoryInitialization(beanFactory);

初始化剩下的单实例bean

为什么说是剩下的bean呢?比如说我们的一些BeanPostProcessor bean,已经在前面创建、初始化并注册到容器中了

// Instantiate all remaining (non-lazy-init) singletons.

beanFactory.preInstantiateSingletons();

这里的beanFactory是DefaultListenableBeanFactory

 

4.1 遍历获取容器中所有的Bean,依次创建对象getBean(beanName);

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

// Trigger initialization of all non-lazy singleton beans...

for (String beanName : beanNames) {
...

else {

   getBean(beanName);

}

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

getBean->doGetBean()->getSingleton()->

4.2 创建bean

AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor会在所有bean创建之前会有一个拦截,因为其实现了InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()

4.2.1 先从缓存中获取当前bean,如果能获取到,说明bean是之前被创建过的,直接使用,否则再创建;

// Eagerly check singleton cache for manually registered singletons.

Object sharedInstance = getSingleton(beanName);

只要创建好的Bean都会被缓存起来,保证单实例Bean只会被创建一次

 

4.2.2 createBean();创建bean;

 

Central method of this class: creates a bean instance,populates the bean instance, applies post-processors, etc.

 

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

 

AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例

BeanPostProcessor后置处理器与InstantiationAwareBeanPostProcessor后置处理器不一样

BeanPostProcessor是在Bean对象创建完成初始化前后调用的

InstantiationAwareBeanPostProcessor是在创建Bean实例之前先尝试用后置处理器返回对象

 

4.2.2.1 resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation

希望后置处理器在此能返回一个代理对象;如果能返回代理对象就使用,如果不能就继续执行doCreateBean

try {

   // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

   Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

   if (bean != null) {

      return bean;

   }

}

后置处理器先尝试返回对象;

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {

   Class<?> targetType = determineTargetType(beanName, mbd);

   if (targetType != null) {

      bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);

      if (bean != null) {

         bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

      }

   }

}

先执行applyBeanPostProcessorsBeforeInstantiation

如果不为null,再执行applyBeanPostProcessorsAfterInitialization

 

拿到所有后置处理器,如果是InstantiationAwareBeanPostProcessor这种类型

注意,我们第3步创建的AnnotationAwareAspectJAutoProxyCreator就是这种类型的BeanPostProcessor

就执行postProcessBeforeInstantiation

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {

   for (BeanPostProcessor bp : getBeanPostProcessors()) {

      if (bp instanceof InstantiationAwareBeanPostProcessor) {

         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

         Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);

         if (result != null) {

            return result;

         }

      }

   }

   return null;

}

 

 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

 

注意看注解:

如果我们有自定义TargetSource,请在此处创建代理。

禁止目标bean的不必要的默认实例化:

TargetSource将以自定义方式处理目标实例。

 

也就是说当注册了AnnotationAwareAspectJAutoProxyCreator之后,再创建任何一个bean的时候,都要先被其拦截一下,看这个bean是直接由这个BeanPostProcessor生成一个proxy对象后返回,还是走常规的创建过程

 

 

4.2.2.2 如果不能,

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

真正的去创建一个bean实例;和3.4创建AnnotationAwareAspectJAutoProxyCreator这个bean流程一样;

5. AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

AnnotationAwareAspectJAutoProxyCreator

其实现了InstantiationAwareBeanPostProcessor

其处理过程

5.1. 每一个bean创建之前,调用postProcessBeforeInstantiation();

关心MathCalculator和LogAspect的创建

 

5.1.1 判断当前bean是否在advisedBeans中(保存了所有需要增强bean)

if (this.advisedBeans.containsKey(cacheKey)) {

   return null;

}

 

5.1.2 判断当前bean是否是基础类型的Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面(@Aspect)

 

 

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {

   this.advisedBeans.put(cacheKey, Boolean.FALSE);

   return null;

}

 

先执行

org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass

return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));

注意在这里判断了是不是@Aspect

 

调用AnnotationUtils类来判断

org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory#hasAspectAnnotation

private boolean hasAspectAnnotation(Class<?> clazz) {

   return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);

}

 

之后再执行

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#isInfrastructureClass

protected boolean isInfrastructureClass(Class<?> beanClass) {

   boolean retVal = Advice.class.isAssignableFrom(beanClass) ||

         Pointcut.class.isAssignableFrom(beanClass) ||

         Advisor.class.isAssignableFrom(beanClass) ||

         AopInfrastructureBean.class.isAssignableFrom(beanClass);

   if (retVal && logger.isTraceEnabled()) {

      logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");

   }

   return retVal;

}

在这里判断是不是Advice、Pointcut、Advisor、AopInfrastructureBean类型

 

5.1.3 判断是否需要跳过

org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#shouldSkip

@Override

protected boolean shouldSkip(Class<?> beanClass, String beanName) {

   // TODO: Consider optimization by caching the list of the aspect names

   List<Advisor> candidateAdvisors = findCandidateAdvisors();

   for (Advisor advisor : candidateAdvisors) {

      if (advisor instanceof AspectJPointcutAdvisor) {

         if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {

            return true;

         }

      }

   }

   return super.shouldSkip(beanClass, beanName);

}

 

5.1.3.1 获取候选的增强器(切面里面的Advice方法)

List<Advisor> candidateAdvisors

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

每一个封装的通知方法的增强器类型是InstantiationModelAwarePointcutAdvisor;

 

判断每一个增强器是否是 AspectJPointcutAdvisor 类型的;

由于我们的增强器类型是InstantiationModelAwarePointcutAdvisor,不是AspectJPointcutAdvisor 类型的

 

5.1.3.2 永远返回false

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip

永远返回false

 

实际上我们的@Aspect切面类会加入到advisedBeans中

this.advisedBeans.put(cacheKey, Boolean.FALSE);

 

 

5.2. 创建对象

调用完postProcessBeforeInstantiation之后,

就要创建对象了

@Bean

public MathCalculator calculator(){

   return new MathCalculator();

}

这个calcalator对象是要创建为代理对象的,要把切面织入进来

 

//切面类加入到容器中

@Bean

public LogAspects logAspects(){

   return new LogAspects();

}

之后调用

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

这个方法的作用:如果bean被标识为(切点表达式)一个代理,那么就使用已配置的拦截器创建代理对象

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

   if (bean != null) {

      Object cacheKey = getCacheKey(bean.getClass(), beanName);

      if (!this.earlyProxyReferences.contains(cacheKey)) {

         return wrapIfNecessary(bean, beanName, cacheKey);

      }

   }

   return bean;

}

 

postProcessAfterInitialization;

                   return wrapIfNecessary(bean, beanName, cacheKey);

//如果需要的情况下包装

 

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

// Create proxy if we have advice.

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;

在这里就创建proxy了

5.2.1 获取当前bean的所有增强器(通知方法)

Object[]  specificInterceptors

 

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

 

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

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;

}

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

5.2.1.1 找到候选的所有的增强器(找哪些Advice方法是能够切入(切点)当前bean方法的)

List<Advisor> candidateAdvisors = findCandidateAdvisors();

 

5.2.1.2 获取到能在bean使用的增强器。

List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

 

5.2.1.3 给增强器排序

eligibleAdvisors = sortAdvisors(eligibleAdvisors);

 

5.2.2 保存当前bean在advisedBeans中;

this.advisedBeans.put(cacheKey, Boolean.TRUE);

 

5.2.3 如果当前bean需要增强,创建当前bean的代理对象;

Object proxy = createProxy(

      bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

 

5.2.3.1 获取所有增强器(Advice方法)

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

 

5.2.3.2 保存到proxyFactory

proxyFactory.addAdvisors(advisors);

 

5.2.3.3 创建代理对象:Spring自动决定

return proxyFactory.getProxy(getProxyClassLoader());

 

JdkDynamicAopProxy(config);jdk动态代理;

ObjenesisCglibAopProxy(config);cglib的动态代理;

 

org.springframework.aop.framework.DefaultAopProxyFactory

@Override

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

   if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

      Class<?> targetClass = config.getTargetClass();

      if (targetClass == null) {

         throw new AopConfigException("TargetSource cannot determine target class: " +

               "Either an interface or a target is required for proxy creation.");

      }

      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

         return new JdkDynamicAopProxy(config);

      }

      return new ObjenesisCglibAopProxy(config);

   }

   else {

      return new JdkDynamicAopProxy(config);

   }

}

 

可以看到,targetClass是

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

5.2.3.4 给容器中返回当前组件使用cglib增强了的代理对象;

我们的calculator未实现接口,所以创建一个cglib增强了的代理对象

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

返回的就是一个增强了的代理对象

 

5.2.3.5 以后容器中获取到的就是这个组件的代理对象

spring aop源码解析2: AnnotationAwareAspectJAutoProxyCreator拦截切点bean(join point)创建过程并生成proxy(在切点织入切面)的过程

执行目标方法的时候,代理对象就会执行增强方法的流程