一、切入点表达式作用
切入点表达式:通过表达式的方式定位一个或多个具体的连接点。
二、语法细节
1、切入点表达式的语法格式
execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))
2、通配符
通配符:
*:
1)匹配一个或者多个字符:execution(public int com.njf.aop.calc.MyMath*r.*(int, int))
2)匹配任意一个参数:第一个是int类型,第二个是任意类型(匹配两个参数)
execution(public int com.njf.aop.calc.MyMath*r.*(int, *))
3)如果 * 放在路径中,只能匹配一层路径
4) 权限位置不能使用 * 表示,权限位置不写就行,public【可选类型】
..:
1)匹配任意多个参数,任意类型参数
2)匹配任意多层路径 execution(public int com.njf..calc.MyMath*r.*(..))
最精确的:execution(public int com.njf.aop.calc.MyMathCalculator.add(int, int))
最模糊的:execution(* *.*(..))
*星号:
1、匹配一个或者多个字符 (MyMath*r)-->开头为MyMath,结尾为r
("execution(public int com.achang.inter.impl.MyMath*r.*(int,int))")
2、匹配任意一个参数 *(int,*) --->任意一个方法,第一个参数为int,第二个为任意类型,有且仅有两个参数
("execution(public int com.achang.inter.impl.MyMathCalculator.*(int,*))")
3、只能匹配一层路径 com.achang.inter.*.MyMathCalculator --->inter路径下任意路径下的MyMathCalculator
("execution(public int com.achang.inter.*.MyMathCalculator.*(int,int))")
4、权限位置*不能:权限位置不写就行
..点点:
1、匹配任意多个参数,任意类型参数 *(..) --->任意方法任意参数
("execution(public int com.achang.inter.impl.MyMathCalculator.*(..))")
2、匹配任意多层路径 impl..MyMath --->impl路径下的任意路径MyMath
("execution(public int com.achang.inter.impl..MyMath.*(int,int))")
举例说明:
execution(* com.atguigu.spring.ArithmeticCalculator.*(..))
ArithmeticCalculator接口中声明的所有方法。
第一个“*”代表任意修饰符及任意返回值。 *
第二个“”代表任意方法。 “…”匹配任意数量、任意类型的参数。
若目标类、接口与该切面类在同一个包中可以省略包名。
3、其他举例
(1)
表达式:execution (* com.spring.aop.ICalc.* (..))
含义
ICalc 接口中声明的所有方法
第一个 '*' 代表任意修饰符及任意返回值;
第二个 '*' 代表任意方法;
'..' 匹配任意数量、任意类型的参数;
若目标类、接口与该切面类在同一个包中可以省略包名
(2)
表达式:execution(public * ICalc.*(..) )
含义:Calc 接口的所有公有方法
(3)
表达式:execution(public double ICalc*(..) )
含义:ICalc 接口中返回 double 类型数值的方法
(4)
表达式:execution(public double ICalc.*(double,..))
含义:
第一个参数为 double 类型的方法
'..' 匹配任意数量、任意类型的参数
(5)
表达式:execution(public double ICalc.*(double,double))
含义:参数类型为 double,doule 类型的方法
4、在AspectJ中,切入点表达式可以通过 “&&”、“||”、“!”等操作符结合起来。
表达式:execution(**.add(int,..)) || execution(**.sub(int,..))
含义:任意类中第一个参数为 int 类型的 add 方法或 sub 方法
表达式:!execution(* *.add(int,...))
含义:匹配不是任意类中第一个参数为 int 类型的 add 方法
三、切入点表达式应用到实际的切面类中
四、重用切入点定义
(1)在编写 AspectJ 切面时,可以直接在通知注解中书写切入点表达式,但同一个切点表达式可能会在多个通知中重复出现;
(2)在 AspectJ 切面中,可以通过 @PointCut 注解将一个切入点声明或简单方法。切入点的方法体通常是空的,因为将切入点定义与应用程序逻辑混在一起是不合理的;
(3)切入点方法的访问控制符同时也控制着这个切入点的可见性。如果切入点要在多个切面中共用,最好将它们集中在一个公共的类中,在这种情况下,它们必须被声明为 public,在引入这个切入点时,必须将类名也包括在内。如果类没有与这个切面放在同一个包中,还必须包含包名。
(4)其他通知可以通过方法名称引入该切入点;
实现步骤:
1、随便声明一个没有实现的返回void的空方法
2、给方法上标注@Pointcut注解
3、在需要用到这个内容的注解execution属性内写入这个空方法的方法名
案例:
代码示例:
@Pointcut(value="execution(* com.spring.aop.*.*(..))") // 重用的切入点表达式
public void test() {}
@Before(value="test()") // 使用前置通知,使用重用的切入点表达式
public void beforeMethod(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();//获取方法的参数
String methodName = joinPoint.getSignature().getName();//获取方法名
System.out.println("method:"+methodName+",arguments:"+Arrays.toString(args));
}
@After(value="test()") // 使用前置通知,使用重用的切入点表达式
public void afterMethod() {
System.out.println("后置通知");
}