面向切面编程
AOP思想
Spring的IoC容器可以使软件组件松耦合,Spring的AOP则可以让你能够捕捉系统中经常使用的功能并把它转化成组件
Spring的AOP的实现底层可以在JDK动态代理 + CGLIB动态代理
两种动态代理中灵活切换,当前也可以通过Spring的配置
强制使用CGLIB动态代理
- 如果代理的是接口默认使用的是JDK动态代理
- 如果代理的是某个类并且这个类没有实现接口使用的就是CGLIB动态代理
交叉业务(切面)
是指在在每一个业务处理过程中掺杂的一些通用且固定不变的非业务逻辑代码,如日志、事务管理、安全监控
相关的逻辑代码
- 交叉业务代码在多个业务流程中反复出现代码没有得到复用,修改这些交叉业务代码的话就需要修改多处
- 程序员在编写核心业务代码的同时还需要处理这些交叉业务是没有必要的
AOP(Aspect Oriented Programming)
又叫面向切面编程或面向方面编程,AOP思想是一种基于OOP基础之上新的编程思想
- 将与核心业务无关的代码独立的抽取出来形成一个独立的组件,然后以横向交叉的方式应用到业务当中的过程被称为AOP
- 优点: 代码复用性增强,代码易维护,使开发者更关注业务逻辑
AOP的七大术语
AOP的七大术语
名称 | 描述 | 位置 |
---|---|---|
连接点(Joinpoint) | 在程序的整个执行流程中可以织入切面的位置 | 方法的执行前后,异常抛出之后 |
切点(Pointcut) | 在程序执行流程中被织入切面的方法(包含核心业务代码) ,一个切点对应多个连接点 | 方法本身 |
通知(Advice)又叫增强 | 具体要织入的增强代码(事务,日志,安全相关的代码),通知都以方法(包含交叉业务代码) 的形式出现在某个连接点上 | 前置通知 : 放在在目标方法之前的连接点上的通知后置通知 :放在在目标方法之后的连接点上的通知环绕通知 :既放在目标方法前又放在目标方法后的连接点上的通知异常通知 :在目标方法抛出异常之后,放在catch语句块中连接点上的通知最终通知 : 放在finally语句块中连接点上的通知 |
切面(Aspect) | 切点(核心代码) + 通知(增强代码)就是切面(完整的业务逻辑) | |
织入 Weaving | 把通知应用到目标对象上的过程 | |
代理对象 Proxy | 一个目标对象被织入通知后产生的新对象 | |
目标对象 Target | 被织入通知的对象 |
public class UserService{public void do1(){System.out.println("do 1");}public void do2(){System.out.println("do 2");}public void do3(){System.out.println("do 3");}public void do4(){System.out.println("do 4");}public void do5(){System.out.println("do 5");}// 核心业务方法public void service(){try{//连接点 Joinpointdo1();//切点 Pointcut//连接点 Joinpointdo2();//切点 Pointcut//连接点 Joinpointdo3();//切点 Pointcut//连接点 Joinpointdo5();//切点 Pointcut//连接点 Joinpoint}catch(Exception e){//连接点 Joinpoint}finally{}//连接点 Joinpoint}
}
切点(方法)表达式
切点表达式
用来定义匹配规则,指定通知往哪些方法上切入
切入表达式的语法格式: execution([访问控制权限修饰符] 返回值类型 全限定类名.方法名(形式参数列表) [异常])
访问控制权限修饰符
: 省略表示4个权限都包括,如public
表示只包括公开的方法返回值类型
:*
表示返回值类型任意全限定类名.方法名
: 省略类名表示所有的类,..
表示代表当前包以及子包下的所有类,*
表示所有方法形式参数列表
:()
表示没有参数,(..)
表示参数类型和个数任意,(*)
表示只有一个参数,(*, String)
表示第一个参数类型随意,第二个参数类型是String的异常
: 省略表示任意异常类型
符号 | 使用场景描述 |
---|---|
* | 在访问修饰符中不能使用 * 在全类名中一个 * 可以匹配一个或者多个字符,但只能匹配一层路径 在方法名中 * 表示匹配任意方法 在形参列表中 一个 * 匹配任意一个的参数类型 |
.. | 在形参列表中匹配任意数量、任意类型的参数 在全限定类名中匹配任意多层路径 |
`&&、 |
//service包下所有的类中以delete开始的所有方法,参数类型参数类型和个数任意
execution(public * com.powernode.mall.service.*.delete*(..))//mall包下所有的类中的所有方法
execution(* com.powernode.mall..*(..)) // 所有类的所有方法
execution(* *(..))