[TOC]
1. 创建并声明一个切面
- 首先,创建一个类,添加
@Component
注解使其添加到IoC容器 - 然后,添加
@Aspect
注解,使其成为一个切面 - 最后,在配置文件里面,使用
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
来使其生效
2. 使用切面的通知
切面总共有6个通知类型,其中五个常用的为:前置通知、后置通知、返回通知、异常通知、环绕通知,一个不常用的为:引入通知。
而在五个常用的通知里,环绕通知功能最为强大,可以实现前四个的功能。
- 前置通知
- 添加
@Before
并指定注解参数:@Before(value = "execution(permission returnType packageName.className.methodName(parameters))")
函数参数为:
JoinPoint
- 后置通知
- 添加
@After
并指定注解参数:@After(value = "execution(permission returnType packageName.className.methodName(parameters))")
- 函数参数为:
JoinPoint
- 返回通知
- 添加
@AfterReturning
并指定注解参数:@AfterReturning(value = "execution(permission returnType packageName.className.methodName(parameters))",returning="result")
- 函数参数为:
JoinPoint, Object
- 异常通知
- 添加
@AfterThrowing
并指定注解参数:@AfterThrowing(value = "execution(permission returnType packageName.className.methodName(parameters))")
函数参数为:
JoinPoint
- 环绕通知
- 添加
@Around
并指定注解参数:@Around(value = "execution(permission returnType packageName.className.methodName(parameters))")
- 函数参数为:
ProceedingJoinPoint
函数返回值为:
Object
首先,上面代码中的名词为:
- permission为访问权限
- retrunType为返回值类型
- packageName为目标(切入对象)的包限定名
- className为目标的类名
- methodName为横切关注点(关注函数)的名字
- parameters为关注点传入的参数(只写类型即可)
其次,上面的注解都有一个隐藏的参数argNames
,此参数可确定传入参数的顺序
3. 定义切面的优先级
当一个横切关注点有多个切面时,我们可能会需要明确切面的执行顺序,此时我们就需要@Order
注解来完成这个工作。
- 首先,明确我们的切面执行顺序
- 然后,在切面的类注解上添加
@Order
注解 - 最后,为
@Order
注解指明参数,比如@Order(1)
注意:参数越小,优先级越高
4. 使用切入点表达式
可能在某种需求下,我们需要为一个关注点织入多个切面、多种通知,那么此时按照上面的做法,为每一个通知函数指定execution
会显得很麻烦,这个时候我们就会用到切入点表达式了。切入点表达式看上去就是一个加了注解的方法,使用时调用该方法就是了。
使用切入点表达式需要按照以下步骤:
- 选择本类或者新建一个专门的切面配置类来容纳切入点表达式
- 声明一个方法比如为
public void cut(){}
,添加@Pointcut
注解 - 像普通的那样为其指明参数
@Pointcut(value = "execution(permission returnType packageName.className.methodName(parameters))")
- 在本类中使用,则在原来通知的value属性上指定该函数即可,比如
@Before(value = "cut()")
- 在其他类中使用,则需要在方法名前加上该方法的所属类名,比如
@Before(value = "className.cut()")
所以,推荐在切面所在包下创建一个切面配置类,而不是所有包共用一个配置类。
需要注意的是,@Pointcut
注解没有returning
参数,故不能带返回值