springboot aop 自定义切面编程
本文结合springboot,实现切面编程。
@Before 前置通知:在某连接点(JoinPoint)之前执行的通知, 但这个通知不能阻止连接点前的执行。
@After 后通知:当某连接点退出的时候执行的通知 (不论是正常返回还是异常退出)。
@AfterReturning 返回后通知 :在某连接点正常完成后执行的通知, 不包括抛出异常的情况。
@Around 环绕通知 :包围一个连接点的通知,类似Web中Servlet ,规范中的Filter的doFilter方法。可以在方法的调用前后完成 自定义的行为,也可以选择不执行。
@AfterThrowing 抛出异常后通知:在方法抛出异常退出时执行的通知。
1. 首先,pom文件引入aop依赖
<!-- spring-boot的aop切面服务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 新建两个类,一个实现切面的处理类,一个定义注解
首先是定义注解:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnnotation {
}
然后是:切面处理类
@Order(2)
@Aspect //定义一个切面
@Configuration
public class TestAspect {
// 定义切点Pointcut
//第一个注解:表示扫描的包或类, 第一个*可以写具体的类,第二个*是方法,括号里是传参
//第二个注解表示定义的注解, 哪个方法需要切面,就在方法上加上 @TestAnnotation
@Pointcut("execution(public * com.example.demo.controller.*.*(..)) && @annotation(com.example.demo.aop.annotation.TestAnnotation)")
public void executeService() {
}
//执行方法之前,进入切面
@Before(value = "executeService()")
public void doBeforeAdvice(JoinPoint joinPoint) {
}
//在进去方法的同时,进入切面
@Around("executeService()")
public Object doAroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletResponse response = sra.getResponse();
HttpServletRequest request = sra.getRequest();
String uri = request.getRequestURI();
Object result = pjp.proceed();
return result;
}
//在执行完方法后,进入切面,并返回方法的结果值,returning定义的参数必须和Object后的形参一致
@AfterReturning(value = "executeService()", returning = "result")
public void doAfterAdvice(JoinPoint joinPoint, Object result) throws Throwable {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
HttpServletResponse response = sra.getResponse();
if (response.getStatus() == 200) {
HttpServletRequest request = sra.getRequest();
String uri = request.getRequestURI();
HttpSession session = request.getSession(true);
Gson gson = new Gson();
JSONObject jsonObject = JSON.parseObject(gson.toJson(result));
}
}
}
具体方法 的注解已经放到代码中,
Gson 的pom依赖:
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
注意:
假如定义了一个切面: 即一个方法只被一个aspect类拦截,aspect类内部的 advice 将按照以下的顺序进行执行:
若同一个方法被多个Aspect类拦截,执行顺序是不一定的。想要有一定的顺序,可以在处理类中加入@Order 注解;
执行顺序如下: