Spring AOP : ReflectiveAspectJAdvisorFactory

概述

使用反射机制,从一个使用AspectJ 5注解@Aspect的组件类中获取相应的AspectJ advice方法,用于创建Spring AOP Advisor。被Spring自动代理机制使用。

这里AspectJ advice注解指的是 @Before,@Around,@After,@AfterReturning,@AfterThrowing

ReflectiveAspectJAdvisorFactory 继承自AbstractAspectJAdvisorFactory,并实现了接口AspectJAdvisorFactorySerializable

基类AbstractAspectJAdvisorFactory主要提供了AspectJAdvisorFactory接口定义的两个方法isAspectvalidate的实现:

  • 方法isAspect检测某个组件类是否使用了注解@Aspect,通过返回值体现;
  • 方法validate通过验证逻辑确保某个组件类使用了注解@Aspect并且能够被Spring AOP支持,通过异常AopConfigException体现;

而关于根据AspectJ advice方法构造Spring AOP Advice/Advisor的逻辑,并不在基类AbstractAspectJAdvisorFactory中提供,而是由其子类ReflectiveAspectJAdvisorFactory提供。

应用举例

该类如何使用可以参考 : AnnotationAwareAspectJAutoProxyCreator/BeanFactoryAspectJAdvisorsBuilder:

// AnnotationAwareAspectJAutoProxyCreator
   @Override
   protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   	super.initBeanFactory(beanFactory);
   	if (this.aspectJAdvisorFactory == null) {
   		this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);// <==
   	}
   	this.aspectJAdvisorsBuilder =
   			new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
   }

// BeanFactoryAspectJAdvisorsBuilder
   public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
   	this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory)); // <==
   }
   
   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<>();
   				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
   						this.beanFactory, Object.class, true, false);
   				for (String beanName : beanNames) {
   					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.
   					Class<?> beanType = this.beanFactory.getType(beanName);
   					if (beanType == null) {
   						continue;
   					}
   					if (this.advisorFactory.isAspect(beanType)) {
   						aspectNames.add(beanName);
   						AspectMetadata amd = new AspectMetadata(beanType, beanName);
   						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
   							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");
   							}
   							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;
   }    

源代码分析

源代码版本 : spring-aop-5.1.5.RELEASE

package org.springframework.aop.aspectj.annotation;

// 省略 import 行

@SuppressWarnings("serial")
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {

	private static final Comparator<Method> METHOD_COMPARATOR;

	static {
		Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
				new InstanceComparator<>(
						Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
				(Converter<Method, Annotation>) method -> {
					AspectJAnnotation<?> annotation =
						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
					return (annotation != null ? annotation.getAnnotation() : null);
				});
		Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
		METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
	}


	@Nullable
	private final BeanFactory beanFactory;


	/**
	 * Create a new ReflectiveAspectJAdvisorFactory.
	 */
	public ReflectiveAspectJAdvisorFactory() {
		this(null);
	}

	/**
	 * Create a new ReflectiveAspectJAdvisorFactory, propagating the given
	 * BeanFactory to the created AspectJExpressionPointcut instances,
	 * for bean pointcut handling as well as consistent ClassLoader resolution.
	 * @param beanFactory the BeanFactory to propagate (may be null)
	 * @since 4.3.6
	 * @see AspectJExpressionPointcut#setBeanFactory
	 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#getBeanClassLoader()
	 */
	public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}


    // 接口 AspectJAdvisorFactory 定义的方法
    // 将使用@Aspect注解的组件类的每个 advice 方法包装成 Spring AOP Advisor
	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
       // 获取使用了注解@Aspect的类
		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 lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
        
       // 获取@Aspect组件类 aspectClass 的每个方法,对其进行遍历,查找其中的 advice 方法,
       // 并将他们包装成 Spring AOP Advisor
       // advice 方法是指使用了 @Before,@Around,@After,@AfterReturning,@AfterThrowing 这些注解的方法
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
       // 获取@Aspect组件类 aspectClass 的每个字段,对其进行遍历,查找其中使用了注解 @DeclareParents
       // 的字段,并将其包装成 Spring AOP Advisor
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

    // 使用反射机制查看类 aspectClass 的每个方法,如果该方法没有使用注解 @Pointcut,
    // 则将其加入到返回列表,最终的返回列表会使用 METHOD_COMPARATOR 进行排序
	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new ArrayList<>();
		ReflectionUtils.doWithMethods(aspectClass, method -> {
			// Exclude pointcuts
			if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
				methods.add(method);
			}
		});
		methods.sort(METHOD_COMPARATOR);
		return methods;
	}

	/**
	 * Build a org.springframework.aop.aspectj.DeclareParentsAdvisor
	 * for the given introduction field.
	 * Resulting Advisors will need to be evaluated for targets.
	 * @param introductionField the field to introspect
	 * @return the Advisor instance, or null if not an Advisor
	 */
	@Nullable
	private Advisor getDeclareParentsAdvisor(Field introductionField) {
		DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
		if (declareParents == null) {
			// Not an introduction field
			return null;
		}

		if (DeclareParents.class == declareParents.defaultImpl()) {
			throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
		}

		return new DeclareParentsAdvisor(
				introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
	}


    // 接口 AspectJAdvisorFactory 定义的方法
    // 根据一个 AspectJ advice 方法构建一个 Spring AOP Advisor
	@Override
	@Nullable
	public Advisor getAdvisor(Method candidateAdviceMethod, 
			MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

       // 获取该 AspectJ advice 方法上 AspectJ advice 注解中的 Pointcut 表达式
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
          // 如果没有 Pointcut 表达式,不需要包装该方法为 Spring AOP Advisor  
			return null;
		}

		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}


    // 接口 AspectJAdvisorFactory 定义的方法
    // 根据一个 AspectJ advice 方法构建一个 Spring AOP Advice
	@Override
	@Nullable
	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);
		if (aspectJAnnotation == null) {
            // 指定的方法 candidateAdviceMethod 上并没有使用 AspectJ advice 注解的方法,
            // 这里AspectJ advice 注解指的是 @Before,@Around,@After,@AfterReturning,@AfterThrowing,@Pointcut
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
      // 现在我们找到了一个使用了 AspectJ advice 注解的方法,继续检测确保当前类使用了注解 @Aspect,  
      // 否则抛出异常
		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;

		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
              // 一个使用了 @Pointcut 注解的方法不包装为 Spring AOP Advice  
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			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);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
        // this.parameterNameDiscoverer 是基类 AbstractAspectJAdvisorFactory 的一个 final 字段,
        // 初始化为 一个AspectJAnnotationParameterNameDiscoverer 对象,用于发现方法参数名称
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
           // 向构建目标 Spring Advice 设置参数名称 
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}


	/**
	 * Synthetic advisor that instantiates the aspect.
	 * Triggered by per-clause pointcut on non-singleton aspect.
	 * The advice has no effect.
	 */
	@SuppressWarnings("serial")
	protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {

		public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
			super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
					(method, args, target) -> aif.getAspectInstance());
		}
	}

}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值