Spring AOP的实现原理

一、基于代理的AOP实现

首先,Spring AOP是一种基于代理(Proxy)的实现,下面这张图很好的表达了这层关系:

这张图反映了参与到AOP过程中的几个关键组件(以@Before Advice为例):

  1. 调用者Beans:即调用的发起者,它只知道目标方法所在Bean,并不清楚代理以及Advice的存在
  2. 目标方法所在Bean:被调用的方法
  3. 生成的代理:由Spring AOP为目标方法所在Bean生成的一个代理对象
  4. Advice:切面的执行逻辑

它们之间的调用先后次序反映在上图的序号中:

  1. 调用者Bean尝试调用目标方法,但是被生成的代理截了胡
  2. 代理根据Advice的种类(本例是@Before Advice),对Advice首先进行调用
  3. 代理调用目标方法
  4. 返回调用结果给调用者Bean(由代理返回,没有体现在图中)

为了理解清楚这张图的意思和代理在中间扮演的角色,不妨看看下面的代码:

@Component
public class SampleBean{
    public void adviceMethod(){
        ...
    }

    public void invokeAdviceMethod(){
        adviceMethod();
    }
}


@Aspect
@Component
public class SampleAspect{
    @Before("execution(void adviceMethod()");
    public void logException(){
        System.out.println("Aspect被调用了");
    }
}

sampleBean.invokeAdviceMethod();  //会打印出"Aspect被调用了吗?"

SampleBean扮演的就是目标方法所在Bean的角色,而SampleAspect扮演的则是Advice的角色。很显然,被AOP修饰过的方法是adviceMethod(),而非invokeAdviceMethod()。然而,invokeAdviceMethod()方法在内部调用了adviceMethod()。那么会打印出Advice的输出吗?

答案是不会

如果想不通为什么会这样,不妨再去仔细看看上面的示意图。

这是在使用Spring AOP的时候可能会遇到的一个问题。类似这种间接调用不会触发Advice的原因在于调用发生在目标方法所在Bean的内部,和外面的代理对象可是没有半毛钱关系哦。我们可以把这个代理想象成一个中介,只有它知道Advice的存在,调用者Bean和目标方法所在Bean知道彼此的存在,但是对于代理或者是Advice却是一无所知的。因此,没有通过代理的调用时绝无可能触发Advice的逻辑的。如下图所示:

二、Spring AOP的两种实现方式

Spring AOP有两种实现方式:

  • 基于接口的动态代理(Dynamic Proxy)
  • 基于子类化的CGLIB代理

基于动态代理和CGLIB这两种方式的简要总结如下:

  • JDK动态代理(Dynamic Proxy)
  1. 基于标准JDK的动态代理功能
  2. 只针对实现了接口的业务对象        
  • CGLIB
  1. 通过动态地对目标对象进行子类化来实现AOP代理
  2. 需要指定@EnableAspectJAutoProxy(proxyTargetClass=true)来强制使用
  3. 当业务对象没有实现任何接口的时候默认会选择CGLIB

转载自:https://www.cnblogs.com/CHENJIAO120/p/7080790.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值