expression表达式分为三部分:指示器,通配符和操作符。
指示器- 匹配方法:execution()
- 匹配注解:@target(),@args(),@within(),@annotation()
- 匹配包/类型:within()
- 匹配对象:this(),bean(),target()
- 匹配参数:args()
- *:匹配任意数量的字符
- +:匹配指定类及其子类
- ..:匹配任意数量的子包或者参数
- &&:与
- ||:或
- !:非
execution()匹配方式使用的较为广泛,其格式如下图所示,其中修饰符和异常可以省略。
@Pointcut("execution(public * studySpring.service.LearnServiceImpl.get*(..))")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
注解匹配:@target(),@args(),@within(),@annotation()
@annotation()可以单独进行使用,其他三种注解,需要指定包或者类。
1. @annotation()匹配标注有指定注解的方法。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation
{
}
// 使用新注解修饰方法
@MyAnnotation
public void learn(String arg)
{
System.out.println("enter function learn");
System.out.println("学习课程:" + arg);
daoImpl.save(arg);
}
// 定义Pointcut,指定注解匹配方法
@Pointcut("@annotation(studySpring.annotation.MyAnnotation)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
2. @target()和@within()匹配标注有指定注解的类中的方法。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TargetWith
{
}
@Component
@TargetWith
public class LearnServiceImpl implements ServiceInterface
{
...
}
// 定义Pointcut,匹配指定注解的类中的所有方法
@Pointcut("@target(studySpring.annotation.TargetWith) && within(studySpring.service..*)")
// @Pointcut("@within(studySpring.annotation.TargetWith) && within(studySpring.service..*)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
3. 当使用@args()注解修饰类的时候,对于只用该类作为参数的方法,被拦截。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TargetWith
{
}
@Component
@MyArgsAnnotation
public class Item
{
public String name;
public int grade;
...
}
// 定义Pointcut,匹配注解修饰的类作为参数的方法
@Pointcut("@args(studySpring.annotation.MyArgsAnnotation) && within(studySpring.service..*)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
匹配包/类型:within()
within主要用于匹配指定的类或者包及其子包下的所有方法。
// 定义切入点
@Pointcut("within(studySpring.service.LearnServiceImpl)")
public void pointCut1(){}
// 定义切入点
@Pointcut("within(studySpring.service..*)")
public void pointCut2(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
// 正常返回后通知
@AfterReturning("pointCut2()")
public void afterReturning()
{
System.out.println("AspectJDemo|afterReturning");
}
对象匹配:this(),target(),bean()
this() 和 target()
的用法大体相同,主要作用有2点。第一,用于匹配实现指定接口的aop代理类;第二,匹配指定类的aop代理类。
bean() 用于匹配指定名称的bean。
1. 匹配实现指定接口的aop代理类(这里使用target和this都可以)
// 匹配实现指定接口的aop代理类,这里使用target和this都可以。
@Pointcut("target(studySpring.interfaces.ServiceInterface)")
// @Pointcut("this(studySpring.interfaces.ServiceInterface)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
@Component
public class LearnServiceImpl implements ServiceInterface
{
public void learn(String arg)
{
System.out.println("enter function learn");
System.out.println("学习课程:" + arg);
daoImpl.save(arg);
}
}
@Component
public class ShopServiceImpl implements ServiceInterface
{
public void getList()
{
System.out.println("enter function ShopServiceImpl.getList()");
System.out.println("黑凤梨");
System.out.println("巧克力");
}
}
2. 匹配指定类的aop代理类(使用target和this都可以)
// 匹配指定类的aop代理类,这里使用target和this都可以。
@Pointcut("target(studySpring.service.LearnServiceImpl)")
// @Pointcut("this(studySpring.service.LearnServiceImpl)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
3. bean() 用于匹配指定名称的bean
// 匹配指定名称的bean:匹配名称中包含Service字符串的bean
@Pointcut("bean(*Service*)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}
参数匹配:args()
用于匹配指定参数类型的方法,比如args(String)
。
还可以结合通配符使用,匹配第一个参数为String的方法:args(String,..)
但是args的匹配方法存在一个使用限制,无法单独使用,必须指定包或者类,否则程序异常。
// 匹配第一个参数类型为String,而且在studySpring.service包中的方法。
@Pointcut("args(String,..) && within(studySpring.service.*)")
// 匹配参数类型为String,而且名称包含Service字段的bean中的方法。
// @Pointcut("args(String) && bean(*Service*)")
public void pointCut1(){}
// 前置通知
@Before("pointCut1()")
public void before()
{
System.out.println("AspectJDemo|before");
}