Spring系列之Spring框架和SpringAOP集成过程分析
Posted 木叶之荣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring系列之Spring框架和SpringAOP集成过程分析相关的知识,希望对你有一定的参考价值。
转载请注明出处:https://blog.csdn.net/zknxx/article/details/80725173
我们在这篇文章中来分析一下AnnotationAwareAspectJAutoProxyCreator这个类,看这个类的名字我们大概可以知道它主要是为AspectJ注解提供服务的类。这个类不得了了是一个相当厉害的类,在这个类中可以识别应用中的所有切面类,为目标类找寻合适的Advisor,将目标类变为代理类等功能。话不多说了,下面我们来简单的分析一下这个类。
首先我们来看一下这个类的类图:
从上面的图中我们可以看到AnnotationAwareAspectJAutoProxyCreator这个类间接实现了BeanFactoryAware、BeanClassLoaderAware、Ordered、BeanPostProcessor接口。如果之前没有了解过Spring Bean的生命周期(或者是Spring开放的对Bean进行修改的扩展接口)的话,请点击这里查看(Spring Bean的生命周期小析(一) 和 Spring Bean的生命周期小析(二))这里就不再多说了。上面提到的接口的实现类大多是在AbstractAutoProxyCreator这个类中实现的。Spring提供的这些关于Bean的扩展接口大大方便了我们在Bean的创建过程中对Bean进行一些修改的操作。我们按照顺序来看看AnnotationAwareAspectJAutoProxyCreator这个关系链上对这些接口的实现。
AbstractAdvisorAutoProxyCreator#setBeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory)
//掉用父类的setBeanFactory 这里只是一个简单的赋值
super.setBeanFactory(beanFactory);
//如果BeanFactory不是ConfigurableListableBeanFactory类型的 抛出异常
if (!(beanFactory instanceof ConfigurableListableBeanFactory))
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
//初始化BeanFactory
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
//这个方法在AnnotationAwareAspectJAutoProxyCreator这个类型中
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory)
//调用父类的initBeanFactory 执行的内容如下:
//this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
//创建BeanFactoryAdvisorRetrievalHelperAdapter 从BeanFactory中获取Advisor类型的Bean
super.initBeanFactory(beanFactory);
if (this.aspectJAdvisorFactory == null)
//创建ReflectiveAspectJAdvisorFactory 相当重要的一个类
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
//创建BeanFactoryAspectJAdvisorsBuilderAdapter 相当重要的一个类
//为目标类型创建对应的Advisor的类
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
AbstractAutoProxyCreator#postProcessBeforeInstantiation
这个方法可以让我们在Bean被Spring容器实例化之前提前创建Bean,如果这个方法返回的值不是null,那就中断其他类对这个接口的实现,直接返回这个创建的Bean。在AbstractAutoProxyCreator中其源码如下:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException
//得到一个缓存的key 实现是:如果是beanClass是FactoryBean类型,则在beanName前面加&
Object cacheKey = getCacheKey(beanClass, beanName);
//如果目标Bean的集合中包这个beanName的话 则跳过
if (beanName == null || !this.targetSourcedBeans.contains(beanName))
if (this.advisedBeans.containsKey(cacheKey))
return null;
//isInfrastructureClass 判断是不是负责AOP基础建设的Bean,如果是AOP基础建设的Bean不能在这里被创建代理对象
//那么什么样的Bean是AOP的基础建设Bean呢?Advice、Pointcut、Advisor、AopInfrastructureBean类型的Bean
//以及含有Aspect注解的Bean
//shouldSkip这个方法是判断这个类型的Bean能不能被跳过,如果可以跳过,那么就不提前创建这个类
//这个类我们在下面详细分析
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName))
//缓存这个beanClass
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)
//一般我们都是不配置TargetSourceCreator 下面的步骤我们先跳过 在后面我们还会继续分析下面的内容的
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;
AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName)
// TODO: Consider optimization by caching the list of the aspect names
//我们重点看到是findCandidateAdvisors这个方法的内容
//查找所有可选择对的Advisor 并且或进行缓存
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors)
if (advisor instanceof AspectJPointcutAdvisor)
//如果AbstractAspectJAdvice类型的Advice中有aspectName和beanName相等则跳过
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName))
return true;
//父类直接返回一个false
return super.shouldSkip(beanClass, beanName);
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors()
// Add all the Spring advisors found according to superclass rules.
// 同样是先调用父类的findCandidateAdvisors
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
//构建所有切面Bean中的Advisor
//很重要的一个方法 下面分析
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
// AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors()
//这个advisorRetrievalHelper 就是我们在 initBeanFactory中创建的BeanFactoryAdvisorRetrievalHelper
return this.advisorRetrievalHelper.findAdvisorBeans();
// BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
//这个方法的内容是从Spring容器中获取Advisor类型的Bean
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)
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
//上面的注释说的很清楚 这里不会初始化FactoryBean 为什么会这样说呢?因为提前导致FactoryBean类型的Bean被创建的话是会有问题的
//从BeanFactory中获取所有的Advisor类型的Bean
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
//这里进行赋值缓存
this.cachedAdvisorBeanNames = advisorNames;
//如果没有Advisor类型的Bean的话 直接返回
//如果你有特殊需求的话 可以实现Advisor接口,并向Spring容器中注入对应的Bean
if (advisorNames.length == 0)
return new LinkedList<Advisor>();
//这里是默认创建了一个 Advisor类型的集合
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames)
//这里默认返回的是true
if (isEligibleBean(name))
//如果是正在创建中的Bean 则跳过
if (this.beanFactory.isCurrentlyInCreation(name))
if (logger.isDebugEnabled())
logger.debug("Skipping currently created advisor '" + name + "'");
else
try
//从BeanFactory中获取对应的Bean 这里如果Bean还没创建 会导致Bean创建
advisors.add(this.beanFactory.getBean(name, Advisor.class));
catch (BeanCreationException ex)
//异常处理 略
return advisors;
下面我们来看看BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors中的这个方法,从名字我们就可以看出来这是一个从BeanFactory中构建Advisor的方法。
public List<Advisor> buildAspectJAdvisors()
//所有的切面的名字 这里的处理逻辑和上面的是一样的 获取到所有的切面BeanName之后缓存起来 volatile类型的
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null)
synchronized (this)
//这里又赋值了一次 看着这个逻辑是不是和某个单例的写法很像啊?
aspectNames = this.aspectBeanNames;
if (aspectNames == null)
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
//这里是从BeanFactory中获取所有的Bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames)
//这里默认都是true
if (!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.
//注意看上面这个注释的内容:在这个场景下我们获取BeanClass的时候必须要小心处理,以免会提前初始化
//Bean,这些Bean在初始化之后会被Spring容器缓存起来,但是这些Bean可能还没有被织入。
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null)
continue;
//判断上面获取到的BeanClass是否带有Aspect注解
if (this.advisorFactory.isAspect(beanType))
//添加到 aspectNames中
aspectNames.add(beanName);
//创建切面元数据 这部门的内容和我们之前分析大致差不多 我们就不再详细分析了
//请看这里: https://blog.csdn.net/zknxx/article/details/79685290
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON)
//注意这里放入了 BeanFactory的引用 方便后面从BeanFactory中获取切面的实例
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
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");
//这里使用的是 PrototypeAspectInstanceFactory
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();
//下面这些就是从缓存中获取Advisor了
List<Advisor> advisors = new LinkedList<Advisor>();
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;
总结起来findCandidateAdvisors这个方法的内容就是从Spring容器中获取所有Advisor类型的Bean和切面中所有带有通知注解的方法并将其封装为Advisor。那么其实我们在AbstractAutoProxyCreator的postProcessBeforeInstantiation方法中就获取到了Spring容器中的所有Advisor。
AbstractAutoProxyCreator#postProcessAfterInstantiation
//通常都是返回true
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName)
return true;
AbstractAutoProxyCreator#postProcessPropertyValues
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
//不做处理
return pvs;
AbstractAutoProxyCreator#postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
//不做处理原样返回
return bean;
AbstractAutoProxyCreator#postProcessAfterInitialization
这个方法需要重点分析一下了
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
if (bean != null)
//获取缓存的key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//如果不是提前引用的Bean
if (!this.earlyProxyReferences.contains(cacheKey))
//如果需要的话 对传入的Bean进行包装
return wrapIfNecessary(bean, beanName, cacheKey);
return bean;
//这个方法的主要作用就是创建代理对象
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)
//如果已经创建过了
if (beanName != null && this.targetSourcedBeans.contains(beanName))
return bean;
//如果这里返回的是False的话 直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey)))
return bean;
//这里又判断了一次不再多说了、、、
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName))
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
//getAdvicesAndAdvisorsForBean这个方法下面我们要重点说一下
// 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;
//如果不需要创建代理对象的话 这里缓存false
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
转载请注明出处:https://blog.csdn.net/zknxx/article/details/80725173
以上是关于Spring系列之Spring框架和SpringAOP集成过程分析的主要内容,如果未能解决你的问题,请参考以下文章
Spring系列之Spring框架和SpringAOP集成过程分析