通配符
* 匹配任意数量字符
//任意返回值,任意名称,任意参数的公共方法
execution(public * *(..))
//匹配com.zejian.dao包及其子包中所有类中的所有方法
within(com.zejian.dao..*)
+ 匹配给定类的任意子类
//匹配实现了DaoUser接口的所有子类的方法
within(com.zejian.dao.DaoUser+)
.. 匹配任意数量参数,任意数量包.
//匹配com.zejian.service包及其子包中所有类的所有方法
within(com.zejian.service..*)
//匹配以set开头,参数为int类型,任意返回值的方法
execution(* set*(int))
execution关键字
方法签名表达式,语法如下:
execution(<scope> <return-type> <fully-qualified-class-name>.function(parameters))
参数解释:
scope :方法作用域。如public、private、protect;不写默认所有方法
returnt-type:方法返回值类型。*代表所有返回类型
fully-qualified-class-name:方法所在类的完全限定名称。.. 表示包及所有子包
function:切入函数名称。*表示所有名称函数
parameters 方法参数。.. 表示所有类型以及个数参数
如:
@Pointcut("execution(* aop..*.*(..))") 可以匹配aop包及其子包下任意类的具有任意返回类型且包含任意参数的任意函数
within关键字
方便按照类型(如接口、类、包)过滤,语法格式:within(<type name>)
type name 使用包名或者类名代替
如:
@Pointcut("within(dao..*)") 可以匹配dao包及其子包中所有类中的所有方法
其他指示符
bean:匹配特定名称的Bean对象的执行方法
//匹配名称中带有后缀Service的Bean。
@Pointcut("bean(*Service)")
this:匹配当前AOP代理对象类型的执行方法
//匹配了任意实现了UserDao接口的代理对象的方法进行过滤
@Pointcut("this(com.zejian.spring.springAop.dao.UserDao)")
target:匹配当前目标对象类型的执行方法
//匹配了任意实现了UserDao接口的目标对象的方法进行过滤
@Pointcut("target(com.zejian.spring.springAop.dao.UserDao)")
@annotation:根据所应有的注解进行方法过滤@within:匹配所有持有制定注解类型内的方法;与within不同
//匹配使用了MarkerAnnotation注解的方法(注意是方法)
@Pointcut("@annotation(com.zejian.spring.annotation.MarkerAnnotation)")
五种通知函数
参数可选:
可以将匹配的方法相应参数或对象自动传递给通知方法,如
@Before(value="args(param)", argNames="param")
public void before(int param) {
System.out.println("param:" + param);
}
优先级:
同一切面内多个通知在同一个切点函数上执行:切点函数前的通知顺序执行,切点函数后的通知逆序执行。
不同切面内多个通知在同一个切点函数上执行:切面实现Ordered接口,并重写getOrder方法返回优先级。切点函数前的通知按照优先级顺序执行,切点函数后的通知按照优先级逆序执行。
五种通知分别为:
- 前置通知@Before
在目标函数执行前执行。joinPoint 参数,可以获取目标对象的信息,如类名称,方法参数,方法名称等。@Before("execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))")
public void before(JoinPoint joinPoint){
System.out.println("前置通知");
} - 后置通知@AfterReturning
该函数在目标函数执行完成后执行,并可以获取到目标函数最终的返回值returnVal。必须通过returning = “returnVal” 注明参数的名称而且必须与通知函数的参数名称相同。@AfterReturning(value="execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))",returning = "returnVal")
public void AfterReturning(JoinPoint joinPoint,Object returnVal){
System.out.println("后置通知...returnVal ="+returnVal);
} - 异常通知@AfterThrowing
该通知只有在异常时才会被触发,并由throwing来声明一个接收异常信息的变量@AfterThrowing(value="execution(* com.zejian.spring.springAop.dao.UserDao.addUser(..))",throwing = "e")
public void afterThrowable(Throwable e){
System.out.println("出现异常:msg="+e.getMessage());
}
- 最终通知@After
类似于finally代码块,只要应用了无论什么情况下都会执行@After("execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))")
public void after(JoinPoint joinPoint) {
System.out.println("最终通知....");
} - 环绕通知@Around
既可以在目标方法前执行也可在目标方法之后执行,更重要的是环绕通知可以控制目标方法是否指向执行。ProceedingJoinPoint,通过该对象的proceed()方法来执行目标函数,proceed()的返回值就是环绕通知的返回值。@Around("execution(* com.zejian.spring.springAop.dao.UserDao.*User(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知前....");
//执行目标函数
Object obj= (Object) joinPoint.proceed();
System.out.println("环绕通知后....");
return obj;
}