spring aspectj 切入点表达式详解
1 切入点表达式
切人点表达式可以按照 修饰注解和修饰和非注解分成2类,带有@的是匹配注解的,没有代@的是匹配非注解的
within 用于限定类型,args 用于限定参数,target 指的限定类型和子类,this 指的调用者类型
1 execution
匹配 指定修饰符 指定返回值类型 指定包 指定类名 指定方法名 指定参数 指定申明异常 的方法
例子1:execution(* com.lomi.aspectj.Fan.*(..)) 表示 Fan和他子类 下面的所有方法
例子2:execution(* com.lomi..Fan.*(..)) 表示 com.lomi包和子包下面 Fan和他子类 下面的所有方法
例子3:execution(String com.lomi.aspectj.Fan.*(..)) 表示 Fan和他子类 下面的所有方法 并且这个方法返回值是 String
例子4:execution(public String com.lomi.aspectj.Fan.*(..)) 表示 Fan和他子类 下面的所有方法 并且这个方法返回值是 String,并且权限修饰符 是 public
例子5: execution(protected * com.lomi.aspectj.Fan.*(..)) 需要 是 protected 的方法
例子6: execution(protected * com.lomi.aspectj.Fan.*(..)) throws IllegalArgumentException) 指明声明的异常
例子7:不能这么写 execution(* String com.lomi.aspectj.Fan.*(..)) 不指定访问修饰符只指定返回值 只能写成 execution( String com.lomi.aspectj.Fan.*(..))
例子8:不能这么写 execution(* * com.lomi.aspectj.Fan.*(..)) 不能这么写 ,只能写成 execution( * com.lomi.aspectj.Fan.*(..))
备注1: execute 功能强大,读的时候可以从方法后面向前面读,会匹配到子类,上面例子2,靠近(..)的*是方法,方法前面是类名,在前面就是包名
备注2:包权限怎么写?只能通过不等于排除吗?
备注3: 权限修饰符 private 可以写,但是 自身调用无效,反射修改可见性以后,调用也无效,存在的意思是啥?
备注4: 权限修饰符和返回值的写法
同时都限定,public String 格式
只有权限修饰符 不限定返回值, 写成 public * 格式
只有 返回值限定不限制 修饰符,修饰符位置必须啥都不写 只能写成
两个都不限定的时候,只能写 一个* 表示都不限定
备注5:只有execution 才能写 修饰符,返回值,参数,别的只能写 类型或者参数,不能写其他
2 within 只能写明确的类型
匹配指定类型 ,不包含子类型,只有自身( 不能指定具体那个方法,不能指定方法修饰符,返回值,参数 )
例子: whin( com.lomi.Uservice )
3 args 只能写参数
匹配方法参数满足指定条件
例子1:args()
例子2:args(..)
例子3:args(String,..)
例子4:args(..,String)
例子5:args(Object,String,Object)
4 target 只能写明确的类型
动态匹配 方法定义在那个类里面的,包含子类型(运行时匹配)( 不能指定具体那个方法,不能指定方法修饰符,返回值,参数 )
例子:target ( com.lomi.Uservice )
5 this 只能写明确的类型
this 指向是 代理对象的类型判断, 和 target 的区别在于 target 是代理目标对象的类型判断( 使用 cglib 代理的时候 this 和 tager 类型判断结果是一样的,使用 jdk 动态代理的时候 this 不能匹配代实现类的类型)
备注:jdk 动态代理的 的代理类 instanceof 实现类 返回 false , instanceof 代理接口 返回 true。
备注:cglib 动态代理的 的代理类 instanceof 实现类 返回 true, instanceof 代理接口 也返回 true。
---------------------------------------------------------@开头的都是描述注解,也是一样只能写确定的注解类型-----------------------------------------------
6 @annotation
匹配 带有指定注解的 方法(指定方法上面有指定注解)
7 @within
匹配 带有指定注解的类(指的是这个类上面有指定的注解)
8 @args
匹配 参数里面带有指定注解的 方法 (匹配参数带有的注解)
9 @target
匹配 带有间接指定注解的类 (父类上写了注解并且这个注解带有继承的源注解)好像和引介增强有关系
2 通配符
1 *
表示指定位置的任意值(可以是 包名,类名,方法名,参数类型 , 方法返回值,方法限定符)
2 ..
表示 所有子包 或者 任意多个参数
3 +
表示 指定类和子类,感觉只有 within 才有效果,within 默认是确定类型,不包括子类,别的都包含当前类型和子类型
within(com.lomi.aspectj.WindProducer+) 等价于 target(com.lomi.aspectj.WindProducer)
3 多个切人点表达式可以通过 && || ! 来实现任意的组合,并且官方建议尽量使用超过一个的切人点表达式来确定 一个切人点,据说这样效率比较高。
例如 "within(com.lomi.UserService)&&args(String)"
UserService里面 只有一个 String参数的 方法
4 aspectj 5种连接点
1.@Before(前置增强)
2.@After(后置增强)
3.@AfterReturning(返回增强)
4.@AfterThrowing(异常增强)
5.@Around(环绕增强)
5 引介增强
通过 DelegatingIntroductionInterceptor类 在不修改源码,只修改xml配置文件 就能做到 给指定类添加增强方法,和普通代理的区别在于普通代理只能给方法增强,引介增强可以添加新的拓展方法或者属性。
下面的配置 给 target 动态的添加了 controlAdvice 的增强,forumService 可以强制装换成 目标类和增强类接口
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean" p:interfaces="com.testApi.yinZhiAdvice.Monitor" //拓展方法的接口定义,forumServer可以强制转成这个接口类型,也可以转换成target类型 p:interceptorNames="controlAdvice" //增强逻辑类,里面写着增强逻辑 p:target-ref="target" //目标类,也就是被增强的类 p:proxyTargetClass="true"/>
posted on 2022-07-16 14:44 zhangyukun 阅读(349) 评论(0) 编辑 收藏 举报