SpringMVC —— 第十八章 基于注解的 AOP 开发
1. 快速入门
基于注解的 AOP 开发步骤:
- 导入 AOP 相关坐标
- 创建目标接口和目标类(内部有切点)
- 创建切面类(内部有增强方法)
- 将目标类和切面类的对象创建权限交给 Spring
- 在切面类中使用注解配置织入关系
- 在配置类中开启组件扫描和 AOP 自动代理
- 测试代码
示例代码:
com.yourname.config.SpringConfiguration
/**
* <code>@EnableAspectJAutoProxy</code>: Enable AOP auto proxy
* @author gregPerlinLi
* @since 2021-09-16
*/
@ComponentScan("com.gregperlinli.*")
@EnableAspectJAutoProxy
public class SpringConfiguration {
}
com.yourname.anno.TargetInterface
public interface TargetInterface {
/**
* save
*/
void save();
}
com.yourname.anno.impl.Target
/**
* @author gregPerlinLi
* @since 2021-09-15
*/
@Component("target")
public class Target implements TargetInterface {
@Override
public void save() {
// int i = 1/0;
System.out.println("Save running...");
}
}
com.yourname.anno.MyAspect
/**
* <code>@Aspect</code> The annotation current class is a aspect class
* @author gregPerlinLi
* @since 2021-09-16
*/
@Component("myAspect")
@Aspect
public class MyAspect {
/**
* Configure before advice
*/
@Before(value = "execution(* com.gregperlinli.anno..*.*(..))")
public void before() {
System.out.println("Front enhance...");
}
@AfterReturning(value = "execution(* com.gregperlinli.anno..*.*(..))")
public void afterReturning() {
System.out.println("Post enhance...");
}
/**
* @param pjp Executing joinpoint => pointcut
*/
@Around(value = "execution(* com.gregperlinli.anno..*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Before around enhance...");
// Pointcut method
Object proceed = pjp.proceed();
System.out.println("After around enhance...");
return proceed;
}
@AfterThrowing(value = "execution(* com.gregperlinli.anno..*.*(..))")
public void afterThrowing() {
System.out.println("Throwing exception enhance...");
}
@After(value = "execution(* com.gregperlinli.anno..*.*(..))")
public void after() {
System.out.println("Final enhance...");
}
}
2. 注解配置 AOP 详解
2.1. 注解通知的类型
通知的配置语法:
@AdviceAnnotation("pointcut expression")
名称 | 标签 | 说明 |
---|---|---|
前置通知 | @Before |
用于配制前置通知,指定的增强方法在切入点方法之后执行 |
后置通知 | @AfterRetruning |
用于配制后置通知,指定点增强方法在切入点方法之后执行 |
环绕通知 | @Around |
用于配制环绕通知,指定增强方法在切入点之前和之后都执行 |
异常抛出通知 | @AfterThrowing |
用于配制异常抛出通知,指定增强方法在出现异常时执行 |
最终通知 | @After |
用于配制最终通知,无论增强方式是否执行是否有异常都会执行 |
2.2. 切点表达式的抽取
同 XML 配置 AOP 一样,我们可以将切点表达式抽取,抽取的方法是在切面内定义方法,在该方法上使用 @Pointcut
注解定义切点表达式,然后再增强注解中进行引用,具体如下:
@Component("myAspect")
@Aspect
public class MyAspect {
@Pointcut(value = "execution(* com.gregperlinli.anno..*.*(..))")
public void myPoint() {}
/**
* Configure before advice
*/
@Before("MyAspect.myPoint()")
public void before() {
System.out.println("Front enhance...");
}
}
3. 知识要点
注解 AOP 开发步骤
- 使用
@Aspect
标注切面类 - 使用
@AdviceAnnotation
标注通知方法 - 在配置类配置 AOP 自动代理注解
@EnableAspectJAutoProxy
- 使用
通知注解类型
名称 标签 说明 前置通知 @Before
用于配制前置通知,指定的增强方法在切入点方法之后执行 后置通知 @AfterRetruning
用于配制后置通知,指定点增强方法在切入点方法之后执行 环绕通知 @Around
用于配制环绕通知,指定增强方法在切入点之前和之后都执行 异常抛出通知 @AfterThrowing
用于配制异常抛出通知,指定增强方法在出现异常时执行 最终通知 @After
用于配制最终通知,无论增强方式是否执行是否有异常都会执行