Spring AOP通俗解释

AOP就是面向切面编程,到底什么意思呢,下面用通俗的话介绍一遍。

为啥要用AOP

  1. 省事方便
    重复的代码不需要导出写,相当于对不同两个维度的代码进行了组合。
  2. 逻辑清晰
    主逻辑可以专注于自己的事情,零碎的与主流程关系不大的事情交给切面完成。比如日志、事务、安全等。

AOP基本概念

1. 通知(advice)

想要增强的功能,就是上文提到的日志、事务、安全等。在通知里面定义好,在别的地方引用。

2. 连接点(JoinPoint)

就是spring允许你使用通知的地方,基本每个方法的前、后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点。其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。

3. 切点(PointCut)

上面提到的连接点都可以选择作为切点,因为我们一般不会在所有的连接点上都加入通知,用切点来筛选连接点,选中需要增强的方法。

4. 切面(Aspect)

通知和切点组合起来就是切面,现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。

5. 引入(Introduction)

允许我们向现有的类添加新方法属性。就是把切面(也就是新方法属性:通知定义的)用到目标类中。

6. 目标(Target)

就是真正的业务逻辑,想要被我们的通知增强的方法。可以在毫不知情的情况下,被咱们织入切面,而自己专注于业务本身的逻辑。

7. 代理(Proxy)

实现AOP的机制。分为静态代理,动态代理(JDK接口实现和CGlib实现)。

8. 织入(Waeving)

把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。

AOP原理

spring用代理类包裹切面,把他们织入到Spring管理的bean中。也就是说代理类伪装成目标类,它会截取对目标类中方法的调用,让调用者对目标类的调用都先变成调用伪装类,伪装类中就先执行了切面,再把调用转发给真正的目标bean(代理)。

现在可以自己想一想,怎么搞出来这个伪装类,才不会被调用者发现(过JVM的检查,JAVA是强类型检查,哪里都要检查类型)。

1. 实现和目标类相同的接口(JDK动态代理)

我(代理类)也实现和你(目标类)一样的接口,反正上层都是接口级别的调用,这样我就伪装成了和目标类一样的类(实现了同一接口,咱是兄弟了),也就逃过了类型检查,到java运行期的时候,利用多态的后期绑定(所以spring采用运行时),伪装类(代理类)就变成了接口的真正实现,而他里面包裹了真实的那个目标类(代理模式),最后实现具体功能的还是目标类,只不过伪装类在之前干了点事情(写日志,安全检查,事物等)。
  打个比方,一个人让你办件事,每次这个时候,你双胞胎弟弟就会先出来,当然求你办事的人分不出来了,以为是你,你这个弟弟虽然办不了这事,但是他知道你能办,所以就答应下来了,并且收了点礼物(写日志),收完礼物了,得给人把事给人家办了啊,所以你弟弟又找你这个哥哥来了,最后把这是办了的还是你自己。但是你自己并不知道你弟弟已经收礼物了,你只是专心把这件事情做好。
  顺着这个思路想,要是本身这个类就没实现一个接口呢,你怎么伪装我,我就压根没有机会让你搞出这个双胞胎的弟弟,那么就用第2种代理方式,创建一个目标类的子类,生个儿子,让儿子伪装我。

2. 生成子类调用(CGlib字节码生成技术)

这次用子类来做为伪装类,当然这样也能逃过JVM的强类型检查,我继承的嘛,当然查不出来了,子类重写了目标类的所有方法,当然在这些重写的方法中,不仅实现了目标类的功能,还在这些功能之前,实现了一些其他的(写日志,安全检查,事物等)。
  打个比方,儿子先从爸爸那把本事都学会了,所有人都找儿子办事情,但是儿子每次办和爸爸同样的事之前,都要收点小礼物(写日志),然后才去办真正的事。当然爸爸是不知道儿子这么干的了。这里就有件事情要说,某些本事是爸爸独有的(final的),儿子学不了,学不了就办不了这件事,办不了这个事情,自然就不能收人家礼了。

总结

第一种兄弟模式,spring会使用JDK的java.lang.reflect.Proxy类,它允许Spring动态生成一个新类来实现必要的接口,织入通知,并且把对这些接口的任何调用都转发到目标类。
  第二种父子模式,spring使用CGLIB库生成目标类的一个子类,在创建这个子类的时候,spring织入通知,并且把对这个子类的调用委托到目标类。
  相比之下,还是兄弟模式好些,他能更好的实现松耦合,尤其在今天都高喊着面向接口编程的情况下,父子模式只是在没有实现接口的时候,也能织入通知,应当做一种例外。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值