SpringAop Aspect与Adivce的执行顺序(一)

    对于同一个连接点,切面与通知的执行顺序有很多种的可能性,我们来分情况进行讨论。

  1. 同一个切面,同一种通知类型

网上有很多的教程说在这种情况下,通知的执行顺序是无法确定的,或者有的说是按照通知的申明顺序执行的,其实通过实际测试都是不准确的。

例:

在上面这个例子中,我们定义了两个前置通知,切入点都是一样的,那么它的执行顺序是怎样的呢?

可以看到控制台的输出是先执行了第一个通知,后执行了第二个通知,似乎是按照通知的申明顺序执行的,但是我们现在将通知的方法名改一下:

再来看一下控制台的输出,可以看到,它并不是按照申明顺序来执行了,而是先执行了第二个通知,然后在执行第一个通知。

我们观察一下这两个通知方法的名称,前面的before都是一样的,后面一个是one一个是four,难道它跟这个单词的意义有关?数字越大越先执行?我们再看下面这个例子:

这个时候我们标注的这两个通知方法名before后面一个是five,一个是ten,如果按照前面的例子推断,应该是ten先执行,也就说第二个通知先执行,第一个通知后执行,我们看一下控制台输出:

可以看到结果恰恰相反,第一个通知先执行了,所以说这个执行的先后顺序是跟名称中数字大小无关的,那么是不是就无法确定它的执行顺序了呢?

我们来看一个例子:

在这个例子中两个通知方法的名字一个是beforer,一个是before_,那么这个时候执行的顺序是先执行第二个通知,再执行第一个通知。

如果修改一下:

那么它的执行顺序会变成先执行第一个通知,再执行第二个通知,我们只是修改了通知方法的名字,将第一个通知的方法名由beforer改成了before0。

所以我们可以看到其实这个执行顺序肯定是跟这个方法名有关系的,那么到底是什么关系呢。

我们查一下ASCII码,r的十进制码是114_的十进制码是95,0的十进制码是48,有意思的地方就出现了,0的十进制码 > _的十进制码 > r的十进制码,我们观察下下面这个例子:

 然后看一下执行顺序:

    这个执行顺序是不是按照十进制码从小到大来执行的?我们可以进一步去验证,比如我现在将第二个通知的名称改为befores,s的十进制码是115,是大于r的十进制码的,所以befores这个通知方法应该后于beforer执行,也就说上面的执行顺序应该变为 前置通知1,前置通知3,前置通知2,我们来验证一下:

     再接下来,我们还可以不改名字,直接调整申明的顺序,比如我们现在将第三个通知放到第一个位置申明,看看执行顺序是否会变化:

可以看到执行的顺序是没有变化的,所以说对于同一个连接点而言,同一个切面里同样类型的通知的执行顺序,实际上是根据通知方法的名称中字母的ASCII码大小决定的,码越小越先执行,码越大越后执行。

在比较的时候,它是根据方法名逐字母去比较的,比如说我们上面那三个方法,它们的名字前面都是一样的,所以就会去比较最后一个字符,如果我们现在将第三个通知方法的第一个字母改成a,因为a的十进制码是大于b的,所以修改后,第三个通知应该是第一个被执行。

最后总结下,在这种情况下,通知的执行顺序是按照方法名,从左往右依次逐字符比较的,只要有一个位置的字符能够确定顺序(也就是不一样),那么就不会再往下比较了,直接根据这个位置两个方法名中字符的ACSII码大小决定通知执行的顺序,ACSII码越小的通知越先执行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值