简介
本文介绍Spring(SpringBoot)的AOP的用法,以及其顺序的控制。
AOP的执行流程图
正常执行时的流程

代码抛异常时的流程

创建工程

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo_springaop-simple</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo_springaop-simple</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.junit.vintage</groupId>-->
<!-- <artifactId>junit-vintage-engine</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
公共代码
启动类
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoSpringaopSimpleApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringaopSimpleApplication.class, args);
}
}
Entity
package com.example.demo.entity;
import lombok.Data;
@Data
public class User {
private Integer id;
private String userName;
private String note;
}
Service
package com.example.demo.service;
import com.example.demo.entity.User;
public interface UserService {
public void printUser(User user);
}
package com.example.demo.service.impl;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public void printUser(User user) {
if (user == null) {
throw new RuntimeException("检查用户参数是否为空");
}
System.out.print("id = " + user.getId());
System.out.print("\t userName = " + user.getUserName());
System.out.println("\t note = " + user.getNote());
}
}
Controller
package com.example.demo.controller;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/user")
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/print")
@ResponseBody
public User testPrint(User user) {
userService.printUser(user);
return user;
}
@RequestMapping("/add")
@ResponseBody
@OperationLog(type = "添加", desc = "添加数据")
public User testAdd(User user) {
return user;
}
@RequestMapping("/update")
@ResponseBody
@OperationLog(type = "更新", desc = "更新数据")
public User testUpdate(User user) {
userService.printUser(user);
return user;
}
}
AOP代码
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import com.sun.org.apache.regexp.internal.RE;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
// @Order(1)
public class SimpleAspect {
@Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
// 多个切点时可指定优先级
// @Order(1)
public void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("############################ SimpleAspect.before ############################");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("############################ SimpleAspect.around ############################");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString());
System.out.println("methodSignature.getName() : " + methodSignature.getName());
System.out.println("method.getName() : " + method.getName());
System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName());
Object[] objects = joinPoint.getArgs();
System.out.println(JsonUtil.toJson(objects));
System.out.println("------------ SimpleAspect.around: proceed之前 ------------");
Object object = joinPoint.proceed();
System.out.println("------------ SimpleAspect.around: proceed返回值 ------------");
System.out.println(JsonUtil.toJson(object));
System.out.println("------------ SimpleAspect.around: proceed之后 ------------");
return object;
}
@AfterReturning(value = "pointcut()", returning = "returnValue")
public void afterReturning(JoinPoint joinPoint, Object returnValue) {
System.out.println("############################ SimpleAspect.afterReturning ############################");
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("------------ SimpleAspect.afterReturning: 方法名字 ------------");
System.out.println(method.getName());
System.out.println("------------ SimpleAspect.afterReturning: 返回值 ------------");
System.out.println(JsonUtil.toJson(returnValue));
}
@AfterThrowing(value = "pointcut()", throwing = "throwingValue")
public void afterThrowing(JoinPoint joinPoint, Throwable throwingValue) {
System.out.println("############################ SimpleAspect.afterThrowing ############################");
// MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// Method method = methodSignature.getMethod();
System.out.println("------------ SimpleAspect.afterThrowing: 异常信息 ------------");
System.out.println(throwingValue.getMessage());
}
/**
* 无法获得返回值,只能获得参数
*/
@After("pointcut()")
public void after() {
System.out.println("############################ SimpleAspect.after ############################");
}
}
测试

后端结果
############################ SimpleAspect.around ############################
joinPoint.getTarget().toString() : com.example.demo.service.impl.UserServiceImpl@36c999c9
methodSignature.getName() : printUser
method.getName() : printUser
method.getReturnType().getName() : void
[{"id":321,"userName":"Tony","note":"abc"}]
------------ SimpleAspect.around: proceed之前 ------------
############################ SimpleAspect.before ############################
id = 321 userName = Tony note = abc
############################ SimpleAspect.afterReturning ############################
------------ SimpleAspect.afterReturning: 方法名字 ------------
printUser
------------ SimpleAspect.afterReturning: 返回值 ------------
null
############################ SimpleAspect.after ############################
------------ SimpleAspect.around: proceed返回值 ------------
null
------------ SimpleAspect.around: proceed之后 ------------
可以看到,返回值为null,因为printUser方法没有返回值。

请先 !