Spring AOP 内部工具类 : BeanFactoryAspectJAdvisorsBuilder

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/86479685

概述

BeanFactoryAspectJAdvisorsBuilder是一个Spring AOP内部工具类,该工具类用来从bean容器,也就是BeanFactory中获取所有使用了@AspectJ注解的bean,最终用于自动代理机制(auto-proxying)。

跟该工具类完成类似工作的另外一个工具类是BeanFactoryAdvisorRetrievalHelper,只不过BeanFactoryAdvisorRetrievalHelper是从容器中获取Spring Advisor bean

该类具体的使用可以参考AnnotationAwareAspectJAutoProxyCreator的嵌套类BeanFactoryAspectJAdvisorsBuilderAdapter

BeanFactoryAspectJAdvisorsBuilder最核心的逻辑在其方法buildAspectJAdvisors中,该方法查找容器中所有@AspectJ注解的bean,然后将其中每个advice方法包装成一个Spring Advisor。最终结果以一个List<Advisor>的形式返回给调用者。

方法buildAspectJAdvisors基本的工作流程如下:

  1. 找到容器中所有的bean;
  2. 遍历每个bean过滤出其中使用了注解@AspectJbean;
  3. 遍历每个找到的使用了注解@AspectJbean中的advice方法,将其封装成一个Spring Advisor对象。最终返回一个List<Advisor>给调用者。

一个使用注解@AspectJbean定义如下所示 :

这是一个带有三个advice方法的AspectJ类,每个advice方法指的是使用注解@AspectJbean类中带有@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;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aspectj.lang.reflect.PerClauseKind;

import org.springframework.aop.Advisor;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

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组织成一个列表返回
	 * @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 内部工具类 : BeanFactoryAdvisorRetrievalHelper

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/86479685
今日推荐