【源码】Spring AOP 7 AspectJAdvisorFactory

前言

此章节介绍 AspectJAdvisorFactory ,这组类主要用于对切面的校验,从切面中解析 AdvisorAdvice

AspectJAdvisorFactory

public interface AspectJAdvisorFactory {

	// 给定class是否切面
	boolean isAspect(Class<?> clazz);
	
	// 是否有效切面
	void validate(Class<?> aspectClass) throws AopConfigException;

	List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);

	@Nullable
	Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrder, String aspectName);

	@Nullable
	Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);

}

负责从基于注解的切面解析 AdvisorAdvice

AbstractAspectJAdvisorFactory

public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {

	// ...

	@Override
	public boolean isAspect(Class<?> clazz) {
		return (hasAspectAnnotation(clazz) && !compiledByAjc(clazz));
	}

	// 有 Aspect 注解才行
	private boolean hasAspectAnnotation(Class<?> clazz) {
		return (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null);
	}
	
	// 至少一个属性前缀为 "ajc$"
	private boolean compiledByAjc(Class<?> clazz) {
		for (Field field : clazz.getDeclaredFields()) {
			if (field.getName().startsWith(AJC_MAGIC)) {
				return true;
			}
		}
		return false;
	}

	// 返回给定方法的第一个 AspectJ 注解
	@SuppressWarnings("unchecked")
	@Nullable
	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}

	// 借助 AnnotationUtils 找给定方法是否有 AspectJ 注解
	@Nullable
	private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {

		// 找到就封装成 AspectJAnnotation 返回,否则 null
		A result = AnnotationUtils.findAnnotation(method, toLookFor);
		if (result != null) {
			return new AspectJAnnotation<>(result);
		}
		else {
			return null;
		}
	}

	// ...

}
  • 抽象基类,主要实现了切面属性的解析校验等工作
  • getAdvisors getAdvisor getAdvice 方法交给子类实现

ReflectiveAspectJAdvisorFactory

public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {

	// ...

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		// AspectJ 实例 -> AspectJ 元数据 -> AspectJ 类
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

		// AspectJ name
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

		// 校验
		validate(aspectClass);

		// 将 aspectInstanceFactory 包装成 ‘缓存’ MetadataAwareAspectInstanceFactory
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		/**
		 * 获取类中所有通知方法,在从方法解析Advisor
		 * Pointcut: AspectJExepressionPointcut
		 * Advice:AbstractAspectJAdvice
		 * Advisor:InstantiationModelAwarePointcutAdvisorImpl
		 */
		List<Advisor> advisors = new ArrayList<>();
		for (Method method : getAdvisorMethods(aspectClass)) {
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// ...

		return advisors;
	}

	// ...

	@Override
	@Nullable
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		// 校验
		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

		// 此处将切点方法转换成一个 AspectJExpressionPointcut 返回
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}

		// 封装成 InstantiationModelAwarePointcutAdvisorImpl 返回
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {

		// 获取方法上第一个 AspectJ 注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// 这样就将把 AspectJ 切点的匹配全部交由 org.aspectj.weaver 相关类完成
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);

		// AspectJAnnotation 将方法上 pointcut 或者 value 的值封装到 pointcutExpression
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

	@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		// 从元数据获取类
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

		// 校验
		validate(candidateAspectClass);

		// AspectJ 注解获取
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// ...

		AbstractAspectJAdvice springAdvice;

		// 根据注解类型实例化成具体的 AbstractAspectJAdvice 
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			
			//...
			
		}

		// ...

		return springAdvice;
	}

	// ...

}
  • AbstractAspectJAdvisorFactory 作为父类完成了 是否切面切面校验方法切面注解获取切面注解封装切面参数解析 等一些列工作,getAdvisors getAdvisor getAdvice 方法交给子类 ReflectiveAspectJAdvisorFactory 实现
  • getAdvisors getAdvisor 方法从 MetadataAwareAspectInstanceFactory 中获取切面元数据信息,将方法切点解析为对应的 AspectJExpressionPointcut,然后封装成 InstantiationModelAwarePointcutAdvisorImpl 返回
  • getAdvice 方法则是基于注解构造对应的 AbstractAspectJAdvice

ReflectionUtils.doWithMethods

一个很有意思的反射工具类方法,过滤对应的方法执行指定回调函数(递归调用它父类、接口的方法)

public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
		Method[] methods = getDeclaredMethods(clazz, false);
		for (Method method : methods) {
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
			}
		}
		if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		else if (clazz.isInterface()) {
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

InstantiationModelAwarePointcutAdvisorImpl

	// 允许延迟加载
	@Override
	public synchronized Advice getAdvice() {
		if (this.instantiatedAdvice == null) {
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
		return this.instantiatedAdvice;
	}

	// Advice 的解析基于 AspectJAdvisorFactory#getAdvice 方法
	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);
	}

上文提到,AspectJAdvisorFactorygetAdvisors 方法将切面上的方法解析成对应的 InstantiationModelAwarePointcutAdvisorImplInstantiationModelAwarePointcutAdvisorImpl 作为一个 PointutAdvisor

  • getPointcut 即返回由 AspectJAdvisorFactory 解析的 AspectJExpressionPointcut 实例
  • getAdvice 则是委托给 AspectJAdvisorFactory#getAdvice 方法,返回对应的 AbstractAspectJAdvice 实例

可以结合以下 demo 理解

demo

public class AspectJAdvisorFactoryDemo {

    @Aspect
    public static class MyAspect {

        @Pointcut("execution(* *.*())")
        public void pointcut() {

        }

        @Before("pointcut()")
        public void before() {

        }
    }

    @Test
    public void test() throws NoSuchMethodException {
        ReflectiveAspectJAdvisorFactory aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory();
        SimpleMetadataAwareAspectInstanceFactory aspectInstanceFactory
                = new SimpleMetadataAwareAspectInstanceFactory(MyAspect.class,
                "myAspect");
        Method m = MyAspect.class.getMethod("before");

        // getAdvisors 方法
        List<Advisor> advisors = aspectJAdvisorFactory.getAdvisors(aspectInstanceFactory);

        // getAdvisor 方法
        Advisor advisor = aspectJAdvisorFactory
                .getAdvisor(m
                        , aspectInstanceFactory, 0
                        , "myAspect");

        // 基于 InstantiationModelAwarePointcutAdvisor 获取 Advice
        // 实际还是委托 AspectJAdvisorFactory#getAdvice
        Advice byAdvisor = null;
        Advice byFactory = null;
        if (advisor instanceof InstantiationModelAwarePointcutAdvisor) {
            InstantiationModelAwarePointcutAdvisor instantiationModelAwarePointcutAdvisor
                    = (InstantiationModelAwarePointcutAdvisor) advisor;
            byAdvisor = instantiationModelAwarePointcutAdvisor.getAdvice();

            // 上述方法其实是基于此方法获取
            byFactory = aspectJAdvisorFactory.getAdvice(
                    m
                    , (AspectJExpressionPointcut) instantiationModelAwarePointcutAdvisor.getPointcut()
                    , aspectInstanceFactory
                    , 0, "myAspect"
            );
        }
    }
}
  • SimpleMetadataAwareAspectInstanceFactory 来实例化切面实例
  • ReflectiveAspectJAdvisorFactorygetAdvisors 方法可以解析上述切面示例中方法对应的 Advisor,这里的实现主要是针对 Aspect 封装成对应的 InstantiationModelAwarePointcutAdvisorImpl
  • getAdvice 方法就是解析对应的 AbstractAspectJAdvice

类图

AspectJAdvisorFactory

序列图

对整个 Advisor Advice 的解析用序列图做进一步总结
getAdvisors

总结

  • AspectJAdvisorFactory 接口主要就是解析切面实例对应的 Advisors Advice
  • 实现类 ReflectiveAspectJAdvisorFactory 主要针对 AspectJ 切面实例的解析
  • InstantiationModelAwarePointcutAdvisorImpl = AspectJExpressionPointcut + AbstractAspectJAdvice

上一篇:【源码】Spring AOP 6 AspectInstanceFactory
下一篇:【源码】Spring AOP 8 TargetSource AdvisorAdapter AdvisorAdapterRegistry AdvisorChainFactory

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值