@PointCut 概览
这个注解包含两部分,PointCut表达式和PointCut签名。表达式是拿来确定切入点的位置的,说白了就是通过一些规则来确定,哪些方法是要增强的,也就是要拦截哪些方法。
注意:
由于是动态代理的实现方法,所以不是所有的方法都能拦截得下来
对于JDK代理只有public的方法才能拦截得下来。
对于CGLIB只有public和protected的方法才能拦截。
支持的表达式类型
@PointCut(...........)括号里面那些就是表达式。括号里支持的类型有:
execution: 匹配连接点
within: 某个类里面
this: 指定AOP代理类的类型
target:指定目标对象的类型
args: 指定参数的类型
bean:指定特定的bean名称,可以使用通配符(Spring自带的)
@target: 带有指定注解的类型
@args: 指定运行时传的参数带有指定的注解
@within: 匹配使用指定注解的类
@annotation:指定方法所应用的注解
-
execution:
execution的匹配方法,大多数时候都会用这个来定义pointcut:
格式:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
execution(方法修饰符(可选) 返回类型 类路径 方法名 参数 异常模式(可选))
其中后面跟着“?”的是可选项括号中各个pattern分别表示:
- 修饰符匹配(modifier-pattern?)
- 返回值匹配(ret-type-pattern): 可以为*表示任何返回值, 全路径的类名等
- 类路径匹配(declaring-type-pattern?)
- 方法名匹配(name-pattern):可以指定方法名 或者 代表所有, set 代表以set开头的所有方法
- 参数匹配((param-pattern)):可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用"" 来表示匹配任意类型的参数,"…"表示零个或多个任意参数。
如(String)表示匹配一个String参数的方法;(,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型。 - 异常类型匹配(throws-pattern?)
除了返回类型,方法名还有参数之外,其他都是可选的
下面给几个例子:
1)execution(public * *(..))——表示匹配所有public方法
2)execution(* set*(..))——表示所有以“set”开头的方法
3)execution(* com.xyz.service.AccountService.*(..))——表示匹配所有AccountService接口的方法
4)execution(* com.xyz.service.*.*(..))——表示匹配service包下所有的方法
5)execution(* com.xyz.service..*.*(..))——表示匹配service包和它的子包下的方法
-
within:
是用来指定类型的,指定类型中的所有方法将被拦截是用来指定类型的,指定类型中的所有方法将被拦截
within(com.demo.service.impl.UserServiceImpl) 匹配UserServiceImpl类对应对象的所有方法调用,并且只能是UserServiceImpl对象,不能是它的子对象
within(com.demo…*)匹配com.demo包及其子包下面的所有类的所有方法的外部调用。
-
this:
SpringAOP是基于代理的,this就代表代理对象,语法是this(type),当生成的代理对象可以转化为type指定的类型时表示匹配。
this(com.demo.service.IUserService)匹配生成的代理对象是IUserService类型的所有方法的外部调用
-
target:
SpringAOP是基于代理的,target表示被代理的目标对象,当被代理的目标对象可以转换为指定的类型时则表示匹配。
target(com.demo.service.IUserService) 匹配所有被代理的目标对象能够转化成IuserService类型的所有方法的外部调用。
-
args:
args用来匹配方法参数
args() 匹配不带参数的方法
args(java.lang.String) 匹配方法参数是String类型的
args(…) 带任意参数的方法
args(java.lang.String,…) 匹配第一个参数是String类型的,其他参数任意。最后一个参数是String的同理。
-
@within 和 @target
带有相应标注的所有类的任意方法,比如@Transactional
@within(org.springframework.transaction.annotation.Transactional)
@target(org.springframework.transaction.annotation.Transactional)
-
@annotation:
带有相应标注的任意方法,比如@Transactional
@annotation(org.springframework.transaction.annotation.Transactional)
@within和@target针对类的注解,@annotation针对方法的注解
-
@args:
参数带有相应标注的任意方法,比如@Transactional
@args(org.springframework.transaction.annotation.Transactional)
Pointcut 的使用
可以通过Java注解和XML两种方式配置
在多个表达式之间使用 ||,or表示 或,使用 &&,and表示 与,!表示 非
1、XML方式配置
<aop:config>
<aop:aspectrefaop:aspectref="aspectDef">
<aop:pointcutidaop:pointcutid="pointcut1"expression="execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))"/>
<aop:before pointcut-ref="pointcut1" method="beforeAdvice" />
</aop:aspect>
</aop:config>
2、注解方式
@Component
@Aspect
public class AspectDef {
// 单表达式
//@Pointcut("execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")
//@Pointcut("within(com.test.spring.aop.pointcutexp..*)")
//@Pointcut("this(com.test.spring.aop.pointcutexp.Intf)")
//@Pointcut("target(com.test.spring.aop.pointcutexp.Intf)")
//@Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
//@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
// 多表达式
//@Pointcut("cutController() && cutService()")
@Pointcut("args(String)")
public void pointcut1() {
}
@Before(value = "pointcut1()")
public void beforeAdvice() {
System.out.println("pointcut1 @Before...");
}