目录

一、简介

二、AbstractAutoProxyCreator#postProcessBeforeInstantiation源码解析

三、总结


一、简介

AnnotationAwareAspectJAutoProxyCreator 实现了几个重要的扩展接口:

  • 1)、实现了 BeanPostProcessor 接口:实现了 postProcessAfterInitialization()方法;
  • 2)、实现了 InstantiationAwareBeanPostProcessor 接口:实现了 postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法;
  • 3)、实现了 SmartInstantiationAwareBeanPostProcessor 接口:实现了 predictBeanType() 方法;getEarlyBeanReference()方法;
  • 4)、实现了 BeanFactoryAware 接口,实现了 setBeanFactory()方法;

本篇文章主要分析AnnotationAwareAspectJAutoProxyCreator 通过间接实现InstantiationAwareBeanPostProcessor接口,在内部主要做了哪些事情?

二、AbstractAutoProxyCreator#postProcessBeforeInstantiation源码解析

AnnotationAwareAspectJAutoProxyCreator类最上面的父类AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,而SmartInstantiationAwareBeanPostProcessor接口继承自InstantiationAwareBeanPostProcessor,在IOC源码中,我们介绍过,InstantiationAwareBeanPostProcessor内部提供了两个方法:

  • postProcessBeforeInstantiation():在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走;
  • postProcessAfterInstantiation():在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null;

InstantiationAwareBeanPostProcessor是在AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation()中执行的,在doCreateBean()实例化bean之前就调用了。

所以,我们需要关注:

AnnotationAwareAspectJAutoProxyCreator

==> AspectJAwareAdvisorAutoProxyCreator

==> AbstractAdvisorAutoProxyCreator

==> AbstractAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator各个间接父类中,postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法的实现过程。

查看上面四个类的源码,发现只有根父类--- AbstractAutoProxyCreator实现了postProcessBeforeInstantiation()、postProcessAfterInstantiation()方法,我们查看具体的实现过程:

  • (一)、postProcessBeforeInstantiation()方法
// AbstractAutoProxyCreator#postProcessBeforeInstantiation
// postProcessBeforeInstantiation()方法在bean实例化之前调用
// 在创建Bean的流程中还没调用构造器来实例化Bean的时候进行调用(实例化前后)
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {// 组装缓存keyObject cacheKey = getCacheKey(beanClass, beanName);if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {// 如果advisedBeans缓存中已经存在,即当前正在创建的Bean已经被解析过,则直接返回nullif (this.advisedBeans.containsKey(cacheKey)) {return null;}// 注意:AnnotationAwareAspectJAutoProxyCreator重写了isInfrastructureClass()方法.// 1.isInfrastructureClass():判断当前正在创建的Bean是否是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)// 2.shouldSkip():判断是不是应该跳过// 满足两个条件其中之一,都将跳过,直接返回nullif (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.// 获取用户自定义TargetSource(目标源)TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}// 获取目标对象的拦截器链Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);// 创建AOP代理Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;
}

AbstractAutoProxyCreator#postProcessBeforeInstantiation()处理流程大体如下:

  1. 根据beanClass和beanName获取缓存Key,通常就是beanName,如果是FactoryBean的话,则是"&"+beanNmae;
  2. 判断当前正在创建的Bean是否已经被解析过,如果已解析,则直接返回null;
  3. 判断当前正在创建的Bean是否是基础的Bean、是否需要跳过等;
  4. 用户自定义TargetSource(目标源)的处理;

AbstractAutoProxyCreator#postProcessBeforeInstantiation()中核心就是下面两个方法:

  • isInfrastructureClass(beanClass)方法

此方法主要判断当前正在创建的Bean是否是基础的Bean,即当前bean是否是Advice、PointCut、Advisor、AopInfrastructureBean。

注意AnnotationAwareAspectJAutoProxyCreator类重写了isInfrastructureClass()方法,真正执行的是下面的代码。

// AnnotationAwareAspectJAutoProxyCreator.isInfrastructureClass
protected boolean isInfrastructureClass(Class<?> beanClass) {// isInfrastructureClass():判断当前正在创建的Bean是否是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)// 或者是否是切面(@Aspect)return (super.isInfrastructureClass(beanClass) ||(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
}// AbstractAutoProxyCreator.isInfrastructureClass
// 判断当前bean是否是基础类,如Advice、Pointcut、Advisor、AopInfrastructureBean
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;
}// 判断是否切面类
public boolean isAspect(Class<?> clazz) {return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
}// 判断是否使用@Aspect注解
private boolean hasAspectAnnotation(Class<?> clazz) {return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
}

可以看到,AnnotationAwareAspectJAutoProxyCreator的isInfrastructureClass()方法除了判断当前正在创建的Bean是否是基础的Bean之外,还判断了当前bean是否是切面。

  • shouldSkip(beanClass, beanName)方法

判断是否需要跳过。

// AbstractAutoProxyCreator.shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}

注意,AbstractAutoProxyCreator的子类----AspectJAwareAdvisorAutoProxyCreator重写了shouldSkip()方法,而AnnotationAwareAspectJAutoProxyCreator又继承自AspectJAwareAdvisorAutoProxyCreator类。

下面我们看下AspectJAwareAdvisorAutoProxyCreator#shouldSkip()方法的源码:

// AspectJAwareAdvisorAutoProxyCreator.shouldSkip
// 判断是否需要跳过
protected boolean shouldSkip(Class<?> beanClass, String beanName) {// 1.获取所有候选的Advisor增强器(即切面里面的通知方法),每个封装的通知方法的增强器的类型为InstantiationModelAwarePointcutAdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 2.循环所有的增强器(通知方法),判断是否是AspectJPointcutAdvisor类型的,如果是的话,则需要跳过。(实际上就是跳过切面类)for (Advisor advisor : candidateAdvisors) {// 判断每个增强器是否是AspectJPointcutAdvisor类型的, 如果是的话则跳过(跳过切面类)if (advisor instanceof AspectJPointcutAdvisor &&((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {return true;}}// 3.调用父类(AbstractAutoProxyCreator)的shouldSkip()方法return super.shouldSkip(beanClass, beanName);
}

shouldSkip()方法的处理流程大体如下:

  1. 获取所有候选的Advisor增强器(即切面里面的通知方法),每个封装的通知方法的增强器的类型为InstantiationModelAwarePointcutAdvisor;
  2. 循环所有的增强器(通知方法),判断是否是AspectJPointcutAdvisor类型的,如果是的话,则需要跳过。(实际上就是跳过切面类);
  3. 调用父类(AbstractAutoProxyCreator)的shouldSkip()方法;

下面我们看一下Spring是如何获取所有候选的Advisor增强器的(即切面里面的通知方法),具体在findCandidateAdvisors()方法,源码如下:

// AbstractAdvisorAutoProxyCreator.findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");// 获取所有候选的Advisor增强器集合return this.advisorRetrievalHelper.findAdvisorBeans();
}

AnnotationAwareAspectJAutoProxyCreator类重写了此方法:

// AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {// Add all the Spring advisors found according to superclass rules.// 1.调用父类AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法找到所有候选的增强器(通知方法)List<Advisor> advisors = super.findCandidateAdvisors();// Build Advisors for all AspectJ aspects in the bean factory.// 2.为bean工厂中的所有的AspectJ切面构建Advisor增强器if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;
}

AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors()处理过程大体如下:

  1. 调用父类AbstractAdvisorAutoProxyCreator.findCandidateAdvisors()方法找到所有候选的增强器(通知方法);
  2. 为bean工厂中的所有的AspectJ切面构建Advisors增强器;

首先来看下如何找到所有候选的增强器(通知方法)的,具体源码在BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():

// BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
// 获取所有符合条件的Advisor增强器,会忽略FactoryBeans以及正在创建中的bean
public List<Advisor> findAdvisorBeans() {// 1.保存增强器对应的beanName集合,并将cachedAdvisorBeanNames缓存的值赋值给它String[] advisorNames = this.cachedAdvisorBeanNames;// 2.如果cachedAdvisorBeanNames缓存为空,则从bean工厂中获取class类型为Advisor的所有bean名称if (advisorNames == null) {// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the auto-proxy creator apply to them!advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);// 3.存入缓存中this.cachedAdvisorBeanNames = advisorNames;}// 如果advisorNames是空的,直接返回空集合if (advisorNames.length == 0) {return new ArrayList<>();}List<Advisor> advisors = new ArrayList<>();// 4.循环遍历前面确定好的增强器对应的beanName集合,确定切面与当前beanName是否符合for (String name : advisorNames) {// isEligibleBean(): 确定切面与当前beanName是否符合,默认都是trueif (isEligibleBean(name)) {// 5.如果当前bean正在创建中的话,什么都不处理if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor '" + name + "'");}} else {try {// 6.根据beanName从工厂中获取对应的bean对象,并添加到advisors集合中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());}// Ignore: indicates a reference back to the bean we're trying to advise.// We want to find advisors other than the currently created bean itself.continue;}}throw ex;}}}}// 7.返回advisors增强器集合return advisors;
}

findAdvisorBeans()方法的整体流程如下:

  1. 获取到cachedAdvisorBeanNames缓存;
  2. 如果cachedAdvisorBeanNames缓存为空,则从bean工厂中获取class类型为Advisor的所有bean名称;
  3. 将上一步获取的bean名称存入缓存中;循环
  4. 遍历前面确定好的增强器对应的beanName集合,确定切面与当前beanName是否符合;
  5. 如果当前bean正在创建中的话,什么都不处理;
  6. 如果当前bean不是正在创建,则根据beanName从工厂中获取对应的bean对象,并添加到advisors集合中;
  7. 返回advisors增强器集合;

当所有候选的增强器找到之后,就需要为bean工厂中的所有的AspectJ切面构建Advisor增强器,具体是在this.aspectJAdvisorsBuilder.buildAspectJAdvisors()完成的。

// BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {// 1.获取aspectBeanNames缓存,如果为空,则会触发切面的解析工作List<String> aspectNames = this.aspectBeanNames;// 解析切面,注意实例化第一个单实例bean的时候就会触发解析切面if (aspectNames == null) {synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {// 用于保存所有解析出来的Advisor增强器List<Advisor> advisors = new ArrayList<>();// 用于保存切面名称aspectNames = new ArrayList<>();// 2.获取工厂中所有的beanNames(bean名称集合)String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);// 3.循环所有的beanNames(bean名称集合),找到增强器for (String beanName : beanNames) {// 跳过不符合条件的beanNameif (!isEligibleBean(beanName)) {continue;}// We must be careful not to instantiate beans eagerly as in this case they// would be cached by the Spring container but would not have been weaved.// 获取beanName对应的bean的类型Class<?> beanType = this.beanFactory.getType(beanName);if (beanType == null) {continue;}// 4.如果存在@Aspect注解的话,则进行解析if (this.advisorFactory.isAspect(beanType)) {// 如果是切面类的话,则将beanName加入到aspectNames中aspectNames.add(beanName);// 根据beanType、beanName创建切面元数据AspectMetadata amd = new AspectMetadata(beanType, beanName);// 如果获取per-clause的类型是SINGLETONif (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {// 创建MetadataAwareAspectInstanceFactory,主要用来创建切面对象实例MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);// 5.获取标记了@AspectJ相关注解的增强方法List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);if (this.beanFactory.isSingleton(beanName)) {// 6.如果当前bean是单例的,则将对应的增强方法加入advisorsCache缓存中this.advisorsCache.put(beanName, classAdvisors);} else {// 7.如果当前bean不是单例的,则将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法this.aspectFactoryCache.put(beanName, factory);}// 将解析的增强器添加到advisors集合中advisors.addAll(classAdvisors);} else {// 如果per-clause的类型不是SINGLETON// 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);// 将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法this.aspectFactoryCache.put(beanName, factory);// 获取标记@AspectJ注解的增强方法advisors.addAll(this.advisorFactory.getAdvisors(factory));}}}// 将解析出来的切面beanName放到缓存aspectBeanNamesthis.aspectBeanNames = aspectNames;return advisors;}}}// 如果经过上述的解析后,缓存aspectNames还是空列表的话,则直接返回一个空列表出去if (aspectNames.isEmpty()) {return Collections.emptyList();}// 存放所有的增强器的集合List<Advisor> advisors = new ArrayList<>();// 8.循环遍历所有解析到的切面名称for (String aspectName : aspectNames) {// 9.根据切面名称从缓存advisorsCache中查找对应的增强器List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);if (cachedAdvisors != null) {// 10.如果缓存中已经存在解析好的Advisor,则直接添加到advisors中advisors.addAll(cachedAdvisors);} else {// 11.缓存中没有,则根据切面beanName从缓存aspectFactoryCache中查找对应的工厂,然后解析出增强器,并添加到advisors中MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);advisors.addAll(this.advisorFactory.getAdvisors(factory));}}// 返回增强器集合return advisors;
}

buildAspectJAdvisors()方法的处理流程:

  1. 获取aspectBeanNames缓存,如果为空,则会触发切面的解析工作;
  2. 获取工厂中所有的beanNames(bean名称集合);
  3. 循环所有的beanNames(bean名称集合),找到增强器;
  4. 如果存在@Aspect注解的话,则进行解析;
  5. 获取标记了@AspectJ相关注解的增强方法;
  6. 如果当前bean是单例的,则将对应的增强方法加入advisorsCache缓存中;
  7. 如果当前bean不是单例的,则将对应的工厂factory加入到aspectFactoryCache缓存中,后面可以通过factory来解析增强方法;
  8. 循环遍历所有解析到的切面名称,根据切面名称从缓存advisorsCache中查找对应的增强器;
  9. 如果缓存中已经存在解析好的Advisor,则直接添加到advisors中;
  10. 缓存中没有,则根据切面beanName从缓存aspectFactoryCache中查找对应的工厂,然后解析出增强器,并添加到advisors中;

上述流程中,比较复杂的方法是this.advisorFactory.getAdvisors(factory):真正的去获取Advisor增强器。

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {// 获取到当前处理的切面类类型Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();// 获取到当前处理的切面类名称String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();// 对切面类进行一些校验validate(aspectClass);// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator so that it will only instantiate once.// 包装MetadataAwareAspectInstanceFactory, 保证只会实例化一次MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);// 存放增强器的集合List<Advisor> advisors = new ArrayList<>();// 获取切面类中的所有通知方法,也就是被@Around、@After等注解修饰的方法,但是会跳过@Pointcut修饰的通知方法for (Method method : getAdvisorMethods(aspectClass)) {// 循环解析切面中的通知方法,将通知方法包装成Advisor增强器Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);if (advisor != null) {// 如果增强器不为空,则添加到advisors集合中advisors.add(advisor);}}// If it's a per target aspect, emit the dummy instantiating aspect.// 如果增强器advisors不为空,而且配置了增强延迟初始化,那么需要在首位加入同步实例化增强器(用以保证增强使用之前的实例化)if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);// 添加到集合中第一个位置advisors.add(0, instantiationAdvisor);}// 获取DeclareParents注解for (Field field : aspectClass.getDeclaredFields()) {Advisor advisor = getDeclareParentsAdvisor(field);if (advisor != null) {advisors.add(advisor);}}return advisors;
}

getAdvisors()方法核心逻辑有两个:

  • 获取切面类中的所有通知方法,并按照规则排序---getAdvisorMethods(aspectClass)方法

也就是被@Around、@After等注解修饰的方法,但是会跳过@Pointcut修饰的通知方法,源码如下:

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisorMethods
private List<Method> getAdvisorMethods(Class<?> aspectClass) {// 1.获取到当前切面类aspectClass的所有通知方法final List<Method> methods = new ArrayList<>();ReflectionUtils.doWithMethods(aspectClass, method -> {// 2.排除掉@Pointcut注解修饰的方法if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {methods.add(method);}}, ReflectionUtils.USER_DECLARED_METHODS);// 3.对通知方法进行排序if (methods.size() > 1) {methods.sort(METHOD_COMPARATOR);}// 4.返回通知方法return methods;
}

  • 将通知方法包装成Advisor增强器---getAdvisor()方法
// 将通知方法包装成Advisor增强器
// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {// 对切面类进行一些校验validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());// 获取切点信息,封装成AspectJExpressionPointcutAspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}// 实例化切面通知对象return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}

getAdvisor()核心就是实例化了一个InstantiationModelAwarePointcutAdvisorImpl切面通知对象,我们查看其构造方法:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {// 切点表达式this.declaredPointcut = declaredPointcut;// 切面的class对象this.declaringClass = aspectJAdviceMethod.getDeclaringClass();// 切面方法的名称this.methodName = aspectJAdviceMethod.getName();// 切面方法的参数类型this.parameterTypes = aspectJAdviceMethod.getParameterTypes();// 切面方法对象this.aspectJAdviceMethod = aspectJAdviceMethod;// aspectj的通知工厂this.aspectJAdvisorFactory = aspectJAdvisorFactory;// aspect的实例工厂this.aspectInstanceFactory = aspectInstanceFactory;// 切面的顺序this.declarationOrder = declarationOrder;// 切面的名称this.aspectName = aspectName;// 判断当前的切面对象是否需要延时加载if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {// Static part of the pointcut is a lazy type.Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.// If it's not a dynamic pointcut, it may be optimized out// by the Spring AOP infrastructure after the first evaluation.this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);this.lazy = true;} else {// 非延迟加载this.pointcut = this.declaredPointcut;this.lazy = false;// 实例化Advice通知对象this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}
}

在InstantiationModelAwarePointcutAdvisorImpl的构造方法中,首先是初始化了一些属性值,然后判断当前的切面对象是否需要延时加载,分别做不同的操作。

如果切面对象是非延迟加载的情况,则会执行实例化Advice通知对象:instantiateAdvice(this.declaredPointcut)。

// org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,this.aspectInstanceFactory, this.declarationOrder, this.aspectName);return (advice != null ? advice : EMPTY_ADVICE);
}

继续跟踪到this.aspectJAdvisorFactory.getAdvice()方法:

// org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {// 获取切面类类型Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();// 校验切面类validate(candidateAspectClass);// 获取切面方法上的注解AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);// 判断解析出来的注解信息是否为nullif (aspectJAnnotation == null) {return null;}// If we get here, we know we have an AspectJ method.// Check that it's an AspectJ-annotated class// 再次校验切面类是否使用了@AspectJ注解if (!isAspect(candidateAspectClass)) {throw new AopConfigException("Advice must be declared inside an aspect type: " +"Offending method '" + candidateAdviceMethod + "' in class [" +candidateAspectClass.getName() + "]");}if (logger.isDebugEnabled()) {logger.debug("Found AspectJ method: " + candidateAdviceMethod);}AbstractAspectJAdvice springAdvice;// 根据方法使用的aspectJ注解创建对应的增强器switch (aspectJAnnotation.getAnnotationType()) {// 如果是PointCut注解,那么就抛出异常case AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;// 如果是@Around环绕通知,则构建AspectJAroundAdvice通知case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;// 如果是@Before前置通知,则构建AspectJMethodBeforeAdvice通知case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;// 如果是@After后置通知,则构建AspectJAfterAdvice通知case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;// 如果是@AfterReturning返回通知,则构建AspectJAfterReturningAdvice通知case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;// 如果是@AfterThrowing异常通知,则构建AspectJAfterThrowingAdvice通知case AtAfterThrowing:springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}break;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// 配置通知对象的相关属性,如设置切面名称、参数等springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;
}

到这里,postProcessBeforeInstantiation()方法整个流程执行完成,已经获取到我们的Advisor增强器。

  • (二)、postProcessAfterInstantiation()方法:直接返回true
public boolean postProcessAfterInstantiation(Object bean, String beanName) {return true;
}

三、总结

最后,通过一张图总结一下AnnotationAwareAspectJAutoProxyCreator实现InstantiationAwareBeanPostProcessor接口底层做的一些工作:

Spring AOP原理分析(四)--AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation源码解析相关推荐

  1. 跟着小马哥学系列之 Spring AOP(基于 XML 定义 Advice 源码解析)

    学好路更宽,钱多少加班. --小马哥 简介 大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间< ...

  2. spring boot2.x设置session有效时间_Spring 源码解析 Scopes 之 Request 、Session 、Application...

    (给ImportNew加星标,提高Java技能) 转自:开源中国,作者:麦克斯 链接:my.oschina.net/wang5v/blog/3017934 Request.Session.Applic ...

  3. Spring Bean的生命周期以及IOC源码解析

    IOC源码这一块太多只能讲个大概吧,建议还是去买本Spring IOC源码解析的书来看比较好,我也是自己看源代码以及视频整理的笔记 Bean的生命周期大概可以分为四个阶段,具体的等会再说,先看看IOC ...

  4. @Import注解:导入配置类的四种方式源码解析

    微信搜索:码农StayUp 主页地址:https://gozhuyinglong.github.io 源码分享:https://github.com/gozhuyinglong/blog-demos ...

  5. Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析

    文章目录 Pre 概览 开天辟地的时候初始化的处理器 @EventListener EventListenerMethodProcessor afterSingletonsInstantiated 小 ...

  6. python整型数据源码分析_Python2 基本数据结构源码解析

    Python2 基本数据结构源码解析 Contents 0x00. Preface 0x01. PyObject 0x01. PyIntObject 0x02. PyFloatObject 0x04. ...

  7. 史上最烂 spring aop 原理分析

    盗引·中篇·spring aop spring aop: jdk 动态代理和 cglib 动态代理的特点.区别.使用方式.原理及各自对反射的优化.二者在 spring 中的统一.通知顺序.从 @Asp ...

  8. spring AOP原理分析:静态代理;JDK实现接口动态代理;Cglib继承父类代理;SpringAop的责任链模式调用

    普通静态代理 代理类和真实类都需要实现同一个接口 接口 package com.fchan.layui.represent.service; /*** 静态代理demo*/ public interf ...

  9. spring源码分析02-spring生命周期源码解析

    spring生命周期流程图: 1.spring扫描 Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象 做准备,所以我们先明白Spring到底是怎 ...

  10. 《Spring》第二十一篇 事务底层源码解析

    目录 一.事务的底层执行原理 1. 解析注解@EnableTransactionManagement 2. Bean生命周期的初始化后阶段,校验是否需要进行AOP 3. 示例FruitsService ...

最新文章

  1. 应届前端面试——看这篇就够了(一)
  2. oa提醒模块要素_OA办公系统的选型有哪些要素?OA系统如何给企业带来巨大价值?...
  3. Python第三、四种数据类型——List(列表) and Tuple(元组)
  4. 正则表达式收藏(五)之微软的正则
  5. Qt学习笔记之常用控件QTreeWidget
  6. Asp.net 批量导入Excel用户数据功能加强版
  7. 7、java中的面向对象思想和体现
  8. [原创]《敏捷软件测试:测试人员与敏捷团队的实践指南》一书思维图初稿版...
  9. oracle导出大数据
  10. webservice调用常见错误原因
  11. 公司电脑加入域的方法
  12. layui框架——弹出层layer
  13. oj-杭电 熊猫阿波的故事
  14. systemverilog : constraint slove... before 详解
  15. 微信单删和互删有什么区别?
  16. Occupancy Flow: 4D Reconstruction by Learning Particle Dynamics(1)
  17. LTspice基础教程-015.导入第三方库
  18. 常用测试工具和框架归类
  19. VPS、SPS、PPS、SS简介
  20. 5G标准必要专利最新全球排名

热门文章

  1. 翻译: 如何使用 Xcode 的内存图调试器检测 iOS 内存泄漏并保留周期
  2. 算法:Validate Binary Search Tree(验证二叉查找树)
  3. 这文字的起始位置_如何用AE快速制造文字特效视频的效果?3分钟教你学会
  4. IGMC,Inductive graph-based matrix completion,基于归纳图的矩阵完成
  5. matlab利用工作区的变量画图,在使用MATLAB“绘图”选项卡中的命令按钮绘图之前,需要( )。 答案:在工作区中选择绘图变量...
  6. mysql 命令创建一个用户名和密码_Mysql的进入数据库指令和创建新用户密码的介绍...
  7. 动态规划 分享巧克力 4794_包装|颇具艺术欣赏性的巧克力创意包装设计
  8. Java 重载和重写
  9. 【生信进阶练习1000days】day7-RSQLite的使用
  10. SYNwall:零配置物联网防火墙