一、AOP底层原理实现
- 假如目标对象(被代理对象)实现接口,则底层默认采用JDK动态代理机制为目标对象创建代理对象(目标类和代理类会实现共同接口)
- 假如目标对象(被代理对象)没有实现接口,则底层默认采用CGLIB代理机制为目标对象创建代理对象(默认创建的代理类会继承目标对象类型)
二、maven 项目添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
三、配置AOP实现
spring配置:
<!-- 启用AOP注解(自动为目标对象创建代理对象) -->
<aop:aspectj-autoproxy/>
或
配置类上使用@EnableAspectJAutoProxy
四、类型通知(Advice)
在AOP编程中有五种类型的通知:
- 前置通知 (@Before) 方法执行之前执行
- 返回通知 (@AfterReturning) 方法return之后执行
- 异常通知 (@AfterThrowing) 方法出现异常之后执行
- 后置通知 (@After) : 又称为最终通知(finally)
- 环绕通知 (@Around) :以上四个一起使用时可以直接使用@Around通知替换
结构如下:
Try{
@Before
核心业务
@AfterReturning
}catch(Exception e){
….
@AfterThrowing
}finally{
….
@After
}
五、切面表达式
指示符 |
作用 |
bean |
用于匹配指定bean id的的方法执行 |
within
|
用于匹配指定包名下类型内的方法执行 |
@annotation |
用于匹配指定注解修饰的方法执行 |
execution |
用于进行细粒度方法匹配执行具体业务 |
bean应用于类级别,实现粗粒度的控制:
bean(userServiceImpl) |
指定一个类 |
bean(*ServiceImpl) |
指定所有的后缀为serviceImpl的类 |
within(aop.service.UserServiceImpl) |
指定类,只能指定一个类 |
within(aop.service.*) |
只包括当前目录下的类 |
within(aop.service..*) |
指定当前目录包含所有子目录中的类 |
execution方法级别,实现细粒度的控制:
语法:execution(返回值类型 包名.类名.方法名(参数列表))
execution(void aop.UserServiceImpl.addUser()) |
匹配方法 |
execution(void aop.UserServiceImpl.addUser(String)) |
方法参数必须为字符串 |
execution(* aop..*.*(..)) |
万能配置 |
@annotaion应用于方法级别,实现细粒度的控制:
@annotation(com.anno.CheckLog) |
指定注解全路径,在需要应用的的方法上加上注解@CheckLog |
六、多个切面作用于同一方法
可在切面上加上@Order(1) @Order(2) @Order(n)...优先执行@Order(1)的切面
七、实例说明
@Order(1)
@Aspect
@Service
public class TestAspect {
@Pointcut("bean(UserServiceImpl)")
// @Pointcut("within(com.*)")
// @Pointcut("execution(* com..*.*(..))")
// @Pointcut("@annotation(com.anno.CheckLog)")
public void doAspect() {}
@Before("doAspect()")
public void before() {
System.out.println("@Before");
}
@After("doAspect()")
public void after() {
System.out.println("@After");
}
@AfterReturning("doAspect()")
public void afterReturning() {
System.out.println("@AfterReturning");
}
@AfterThrowing("doAspect()")
public void afterThrowing() {
System.out.println("@AfterThrowing");
}
@Around("doAspect()")
public Object around(ProceedingJoinPoint joinPoint)
throws Throwable{
try{
System.out.println("@Around before");
Object result = joinPoint.proceed();
System.out.println("@AfterReturning");
return result;
}catch(Exception e){
System.out.println("@AfterThrowing");
throw e;
}finally{
System.out.println("@After");
}
}
}