Spring的AOP执行顺序


前言

当一个方法上面上面加了多个AOP注解的时候,运行顺序是如何的呢?


一、问题的提出

我们想对某个加了@Transactional注解的方法再添加一个自定义注解,来进行日志的打印。此时一个问题就出现在脑海里了:到底是先运行@Transactional注解的逻辑还是先运行自定义注解的逻辑呢?自定义注解实现的逻辑会在事务里么?也就是如果抛出异常会使得事务回滚么?

二、思考的逻辑

1. advisor运行的顺序

基于我们以前的了解,最后bean会被封装成一个proxy,proxy里的target才是raw bean。在method进行invoke的时候,需要遍历proxy里的advisors。
此处我们以CglibAopProxy为例,JdkDynamicAopProxy逻辑类似。

class CglibAopProxy implements AopProxy, Serializable {
   
// 其他属性本文不会涉及,暂时忽略
/** The configuration used to configure this proxy. */
	protected final AdvisedSupport advised;
}

可以看到CglibAopProxy里有个advised属性。

public class AdvisedSupport extends ProxyConfig implements Advised{
   
	// 其余属性忽略
	/**
	 * Canonical TargetSource when there's no target, and behavior is
	 * supplied by the advisors.
	 */
	public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;

	/** Package-protected to allow direct access for efficiency. */
	TargetSource targetSource = EMPTY_TARGET_SOURCE;
	/**
	 * List of Advisors. If an Advice is added, it will be wrapped
	 * in an Advisor before being added to this List.
	 */
	private List<Advisor> advisors = new ArrayList<>();
}

可以看到advised属性里的targetSource和advisors,分别代表目标方法和相应的advisor。
执行的时候是遍历advisors,把每个advisor里的advice拿出来,然后进行链式调用,具体使用方式类似filter。
那么advisors里的advisor顺序就变得尤为重要。
那么此处我们反推,在生成CglibAopProxy的时候,放入进去的advisors顺序是如何的?咱们去往回找代码。

2. advisor添加的顺序

相信大家看过我之前的博客,应该知道给raw bean变成aop proxy是在AbstractAutoProxyCreator里的wrapIfNecessary
在wrapIfNecessary中调用了createProxy方法

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
   

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
   
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		// 创建一个ProxyFactory,并把当前对象的某些属性拷贝填充到该proxyFactory对象上
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
   
			if (shouldProxyTargetClass(beanClass, beanName)) {
   
				proxyFactory.setProxyTargetClass(tr
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值