Aop
与OOP对比,传统的OOP开发中的代码逻辑是自上而下的,而这些过程会产生一些横切性问题,但是这些问题和业务关系不大,也不会影响主逻辑,但是会散落到代码的各个部分,难以维护。而AOP的编程思想就是把这些问题和主业务逻辑分开,达到与主业务逻辑解耦的目的。使代码的重用性和开发效率更高。
应用场景:日志记录、权限验证、效率检查、事务管理、exception。
JDK动态代理 | CGLIB代理 | |
---|---|---|
编译时期的织入还是运行时期的织入? | 运行时期织入 | 运行时期织入 |
初始化时期织入还是获取对象时期织入? | 初始化时期织入 | 初始化时期织入 |
SpringAop和AspectJ的关系
Aop是一种概念,springAop、AspectJ都是Aop的实现,SpringAop有自己的语法,但是语法复杂,所以SpringAop借助了AspectJ的注解,但是底层实现还是自己的。
spring AOP提供两种编程风格
1 | @AspectJ support 利用aspectj的注解 |
Spring Aop的概念
1 | aspect:一定要给spring去管理 |
advice通知类型
1 | Before 连接点执行之前,但是无法阻止连接点的正常执行,除非该段执行抛出异常 |
Proceedingjoinpoint 和JoinPoint的区别
Proceedingjoinpoint 继承了JoinPoint,并扩充实现了proceed()方法,用于继续执行连接点。JoinPoint仅能获取相关参数,无法执行连接点。
JoinPoint的方法
1 | 1.java.lang.Object[] getArgs():获取连接点方法运行时的入参列表; |
Introductions
通过将需要添加的新的行为逻辑,以新的接口定义增加到目标对象上。以@Aspect声明一个实列变量,它的类型对应的是新增加的接口类型,然后通过DeclareParents对其进行标注。通过@DeclareParents指定新接口定义的实现类以及将要加诸其上的目标对象。简单来说就是可以扩展原有的目标对象。
例如,给定名为的接口UsageTracked和名为的接口的实现DefaultUsageTracked,新声明服务接口的所有实现者也都实现该UsageTracked接口
1 |
|
切面模型 perthis
perthis:每个切入点表达式匹配的连接点对应的AOP对象都会创建一个新的切面实例,使用@Aspect(“perthis(切入点表达式)”)指定切入点表达式;默认的情况下多个连接点对应的切面对象是一个。
使用方式如下:
@Aspect(“perthis(com.xyz.myapp.SystemArchitecture.businessService())”)
1 | 1. AspectJ对象的注入类型为prototype |
原因:只有目标对象是原型模式的,每次getBean得到的对象才是不一样的,由此针对每个对象就会产生新的切面对象,才能产生不同的切面结果。
SpringAop支持AspectJ
启用@AspectJ支持
1 |
|
XML配置启用@AspectJ支持:aop:aspectj-autoproxy/
声明一个Aspect
1 |
|
声明切点pointCut
1 | "execution(* transfer(..))")// 切入点表达式 ( |
Advice通知
1 | "com.xyz.myapp.SystemArchitecture.dataAccessOperation()") ( |
AspectJ切入点指示符(PCD):
execution
用于匹配方法执行的连接点。这是使用Spring AOP时要使用的主要切入点指示符。最小粒度方法。
1 | execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?) |
within
将匹配限制为某些类型内的连接点(使用Spring AOP时,在匹配类型内声明的方法的执行)。
1 | within与execution相比,粒度更大,仅能实现到包和接口、类级别。而execution可以精确到方法的返回值,参数个数、修饰符、参数类型等 |
this
限制匹配到连接点(使用Spring AOP时方法的执行)的匹配,其中bean引用(Spring AOP代理)是给定类型的实例。
JDK代理时,指向接口和代理类proxy,cglib代理时 指向接口和子类(不使用proxy)
target
在目标对象(代理的应用程序对象)是给定类型的实例的情况下,将匹配限制为连接点(使用Spring AOP时方法的执行)。
1 | 如果配置设置proxyTargetClass=false,或默认为false,则是用JDK代理,否则使用的是CGLIB代理 |
args
在参数为给定类型的实例的情况下,将匹配指定参数类型和指定参数数量的方法,与包名和类名无关。
1 | /** |
@target
在执行对象的类具有给定类型的注释的情况下,将匹配限制为连接点(使用Spring AOP时方法的执行)。
@args
限制匹配的连接点(使用Spring AOP时方法的执行),其中传递的实际参数的运行时类型具有给定类型的注释。
@within
将匹配限制为具有给定注释的类型内的连接点(使用Spring AOP时,使用给定注释的类型中声明的方法的执行)。
@annotation
将匹配限制在连接点的主题(Spring AOP中正在执行的方法)具有给定注释的连接点上。
1 | 作用方法级别 上述所有表达式都有@ 比如@Target(里面是一个注解类xx,表示所有加了xx注解的类,和包名无关) |