概述
BeanFactoryAspectJAdvisorsBuilder是一个Spring AOP内部工具类,该工具类用来从bean容器,也就是BeanFactory中获取所有使用了@AspectJ注解的bean,最终用于自动代理机制(auto-proxying)。
该工具内部使用了缓存机制,虽然公开的查找方法可能会被调用多次,但并不是每次都会真正查找,而是会利用缓存。
跟该工具类完成类似工作的另外一个工具类是
BeanFactoryAdvisorRetrievalHelper,只不过BeanFactoryAdvisorRetrievalHelper是从容器中获取SpringAdvisorbean: 也就是实现了接口org.springframework.aop.Advisor的bean。
该类具体的使用可以参考
AnnotationAwareAspectJAutoProxyCreator的嵌套类BeanFactoryAspectJAdvisorsBuilderAdapter。
BeanFactoryAspectJAdvisorsBuilder最核心的逻辑在其方法buildAspectJAdvisors中,该方法查找容器中所有@AspectJ注解的bean,然后将其中每个advice方法包装成一个Spring Advisor。最终结果以一个List<Advisor>的形式返回给调用者。
方法buildAspectJAdvisors基本的工作流程如下:
- 找到容器中所有的
bean; - 遍历每个
bean过滤出其中使用了注解@AspectJ的bean; - 遍历每个找到的使用了注解
@AspectJ的bean中的advice方法,将其封装成一个Spring Advisor对象。最终返回一个List<Advisor>给调用者。
一个使用注解@AspectJ的bean定义如下所示 :
这是一个带有三个
advice方法的AspectJ类,每个advice方法指的是使用注解@AspectJ的bean类中带有@Before,@Around,@AfterReturning这样的AspectJ advice注解的方法。
/**
* 定义一个和切入点配合使用的切面类,切入点基于另外一个注解
*/
@Aspect
@Component
public class AspectAnnotationPointcut {
/**
* 定义一个切入点
*/
@Pointcut(value = "@annotation(RecordLogin)")
public void webControllerMethodLogin() {
}
// 注意:这里使用了上面的定义的切入点 webControllerMethodLogin()
@Before("webControllerMethodLogin()")
public void doBefore(JoinPoint joinPoint) {
// ...
}
// 注意:这里使用了上面的定义的切入点 webControllerMethodLogin()
@Around(value = "webControllerMethodLogin()")
public Object doProcess(ProceedingJoinPoint joinPoint) {
// ...
}
// 注意:这里使用了上面的定义的切入点 webControllerMethodLogin()
@AfterReturning(returning = "ret", pointcut = "webControllerMethodLogin()")
public void doAfterReturning(Object ret) {
// ...
}
}
源代码解析
package org.springframework.aop.aspectj.annotation;
public class BeanFactoryAspectJAdvisorsBuilder {
private final ListableBeanFactory beanFactory;
private final AspectJAdvisorFactory advisorFactory;
@Nullable
private volatile List<String> aspectBeanNames;
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache =
new ConcurrentHashMap<>();
/**
* Create a new BeanFactoryAspectJAdvisorsBuilder for the given BeanFactory.
* @param beanFactory the ListableBeanFactory to scan
*/
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
}
/**
* Create a new BeanFactoryAspectJAdvisorsBuilder for the given BeanFactory.
* @param beanFactory the ListableBeanFactory to scan
* @param advisorFactory the AspectJAdvisorFactory to build each Advisor with
*/
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory,
AspectJAdvisorFactory advisorFactory) {
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
this.beanFactory = beanFactory;
this.advisorFactory = advisorFactory;
}
/**
* Look for AspectJ-annotated aspect beans in the current bean factory,
* and return to a list of Spring AOP Advisors representing them.
* Creates a Spring Advisor for each AspectJ advice method.
* 此方法将所有 @AspectJ bean advice 方法包装成Spring Advisor列表返回:
* 1. 从容器中找到所有@AspectJ注解的bean;
* 2. 将找到的每个@AspectJ bean的每个advice方法封装成一个Spring Advisor;
* 3. 缓存找到的Spring Advisor;
* 4. 将上述找到的所有Spring Advisor组织成一个列表返回
* @return the list of org.springframework.aop.Advisor beans
* @see #isEligibleBean
*/
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// 获取所有类型为Object的bean的名称,基本上也就是说所有的bean的名称了
// includeNonSingletons:true=>包含单例,非单例bean
// allowEagerInit:false=>不要初始化lazy-init singletons和FactoryBean创建的bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
// 本实例自己提供的筛查条件,缺省实现总是返回true,
// 子类可以覆盖该方法提供自己的实现
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.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 检测该bean是否使用了注解@AspectJ
if (this.advisorFactory.isAspect(beanType)) {
// 检测到了一个使用注解@AspectJ的bean
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() ==
PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory,
beanName);
// 从@AspectJ注解的类,也就是AspectJ切面类中分析
// 其advice方法,每个构造成一个Spring Advisor,
// pointcut 信息 和 advice 信息已经包含在相应的Advisor
// 对象中
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");
}
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();
}
List<Advisor> advisors = new ArrayList<>();
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;
}
/**
* Return whether the aspect bean with the given name is eligible.
* @param beanName the name of the aspect bean
* @return whether the bean is eligible
*/
protected boolean isEligibleBean(String beanName) {
return true;
}
}

本文详细介绍了Spring AOP框架中BeanFactoryAspectJAdvisorsBuilder的作用与工作原理,该工具类负责从BeanFactory中查找所有使用了@AspectJ注解的bean,并将这些bean的advice方法转换为Spring Advisor,用于实现自动代理机制。通过缓存机制提高查找效率,避免重复劳动。
168万+

被折叠的 条评论
为什么被折叠?



