AOP概述
AOP称为面向切面编程,那我们怎么理解面向切面编程?
我们学Java面向对象的时候,如果代码重复了怎么办啊?可以分成下面几个步骤:
- 抽取成方法
- 抽取类
抽取成类的方式我们称之为:纵向抽取
- 通过继承的方式实现纵向抽取
但是,我们现在的办法不行:即使抽取成类还是会出现重复的代码,因为这些逻辑(开始、结束、提交事务)依附在我们业务类的方法逻辑中!
现在纵向抽取的方式不行了,AOP的理念:就是将分散在各个业务逻辑代码中相同的代码通过横向切割的方式抽取到一个独立的模块中!
上面的图也很清晰了,将重复性的逻辑代码横切出来其实很容易(我们简单可认为就是封装成一个类就好了),但我们要将这些被我们横切出来的逻辑代码融合到业务逻辑中,来完成和之前(没抽取前)一样的功能!这就是AOP首要解决的问题了!
Spring AOP原理
被我们横切出来的逻辑代码融合到业务逻辑中,来完成和之前(没抽取前)一样的功能
Spring AOP构建在动态代理基础之上,因此,Spring对AOP的支持局限于方法拦截。
在Java中动态代理有两种方式:
JDK动态代理
CGLib动态代理
JDK动态代理是需要实现某个接口了,而我们类未必全部会有接口,于是CGLib代理就有了~~
- CGLib代理其生成的动态代理对象是目标类的子类
- Spring AOP默认是使用JDK动态代理,如果代理的类没有接口则会使用CGLib代理。
那么JDK代理和CGLib代理我们该用哪个呢??在《精通Spring4.x 企业应用开发实战》给出了建议:
- 如果是单例的我们最好使用CGLib代理,如果是多例的我们最好使用JDK代理
原因:
- JDK在创建代理对象时的性能要高于CGLib代理,而生成代理对象的运行性能却比CGLib的低。
- 如果是单例的代理,推荐使用CGLib
看到这里我们就应该知道什么是Spring AOP(面向切面编程)了:将相同逻辑的重复代码横向抽取出来,使用动态代理技术将这些重复代码织入到目标对象方法中,实现和原来一样的功能。
- 这样一来,我们就在写业务时只关心业务代码,而不用关心与业务无关的代码
AOP的术语
连接点(Join point):
- 能够被拦截的地方:Spring AOP是基于动态代理的,所以是方法拦截的。每个成员方法都可以称之为连接点
切点(Poincut):
- 具体定位的连接点:上面也说了,每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点。
增强/通知(Advice):
- 表示添加到切点的一段逻辑代码,并定位连接点的方位信息。
- 简单来说就定义了是干什么的,具体是在哪干
- Spring AOP提供了5种Advice类型给我们:前置、后置、返回、异常、环绕给我们使用!
织入(Weaving):
- 将
增强/通知
添加到目标类的具体连接点上的过程。
引入/引介(Introduction):
引入/引介
允许我们向现有的类添加新方法或属性。是一种特殊的增强!
切面(Aspect):
- 切面由切点和
增强/通知
组成,它既包括了横切逻辑的定义、也包括了连接点的定义。
在《Spring 实战 (第4版)》给出的
通知/增强包含了需要用于多个应用对象的横切行为;连接点是程序执行过程中能够应用通知的所有点;切点定义了通知/增强被应用的具体位置。其中关键的是切点定义了哪些连接点会得到通知/增强。