简介
说明
本文介绍Spring的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
    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(单个Aspect正常操作)
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SimpleAspect.around1:" + "around before");
        joinPoint.proceed();
        System.out.println("SimpleAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}测试
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
SimpleAspect.around1:around before
SimpleAspect.before
id = 321   userName = Tony   note = abc
SimpleAspect.afterReturning
SimpleAspect.after
SimpleAspect.around1:around afterpostman结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}单AOP(不调用jointPoint.proceed())
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around2(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SimpleAspect.around2:"+ "around before");
//        joinPoint.proceed();
        System.out.println("SimpleAspect.around2:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}测试
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
SimpleAspect.around2:around before
SimpleAspect.around2:around afterpostman结果
SimpleAspect.around2:around before
SimpleAspect.around2:around after单AOP(只打印joinPoint信息)
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around3(ProceedingJoinPoint joinPoint) throws Throwable {
        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();
        for (Object o : objects) {
            System.out.println(o);
            if (o instanceof User) {
                System.out.println("id是:" + ((User)(o)).getId() +
                        "; 名字是:" + ((User)(o)).getUserName() +
                        "; 备注是:" + ((User)(o)).getNote());
            }
        }
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}测试
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
joinPoint.getTarget().toString()  : com.example.demo.service.impl.UserServiceImpl@279268ba
methodSignature.getName()         : printUser
method.getName()                  : printUser
method.getReturnType().getName()  : void
User(id=321, userName=Tony, note=abc)
id是:321; 名字是:Tony; 备注是:abcpostman结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}两AOP+@Order(都不调用proceed())
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around2(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SimpleAspect.around2:"+ "around before");
//        joinPoint.proceed();
        System.out.println("SimpleAspect.around2:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}package com.example.demo.aspect;
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(2)
public class OrderTestAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("OrderTestAspect.before");
    }
    @Around("pointCut()")
    public void around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("OrderTestAspect.around1:" + "around before");
//        joinPoint.proceed();
        System.out.println("OrderTestAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("OrderTestAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("OrderTestAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("OrderTestAspect.afterThrowing");
    }
}测试
正常顺序
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
SimpleAspect.around2:around before
SimpleAspect.around2:around after前端结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}颠倒顺序
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
OrderTestAspect.around1:around before
OrderTestAspect.around1:around after前端结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}两AOP+@Order(都调用proceed())
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SimpleAspect.around1:" + "around before");
        joinPoint.proceed();
        System.out.println("SimpleAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}package com.example.demo.aspect;
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(2)
public class OrderTestAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("OrderTestAspect.before");
    }
    @Around("pointCut()")
    public void around2(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("OrderTestAspect.around1:" + "around before");
        joinPoint.proceed();
        System.out.println("OrderTestAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("OrderTestAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("OrderTestAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("OrderTestAspect.afterThrowing");
    }
}测试
正常顺序
后端结果
SimpleAspect.around1:around before
SimpleAspect.before
OrderTestAspect.around1:around before
OrderTestAspect.before
id = 321   userName = Tony   note = abc
OrderTestAspect.afterReturning
OrderTestAspect.after
OrderTestAspect.around1:around after
SimpleAspect.afterReturning
SimpleAspect.after
SimpleAspect.around1:around afterpostman结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}颠倒顺序之后
后端结果
OrderTestAspect.around1:around before
OrderTestAspect.before
SimpleAspect.around1:around before
SimpleAspect.before
id = 321   userName = Tony   note = abc
SimpleAspect.afterReturning
SimpleAspect.after
SimpleAspect.around1:around after
OrderTestAspect.afterReturning
OrderTestAspect.after
OrderTestAspect.around1:around afterpostman结果:
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}两AOP+@Order(高优先级调用proceed())
代码
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
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(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("SimpleAspect.before");
    }
    @Around("pointCut()")
    public void around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SimpleAspect.around1:" + "around before");
        joinPoint.proceed();
        System.out.println("SimpleAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("SimpleAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("SimpleAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("SimpleAspect.afterThrowing");
    }
}package com.example.demo.aspect;
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(2)
public class OrderTestAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {
    }
    @Before("pointCut()")
    public void before() {
        System.out.println("OrderTestAspect.before");
    }
    @Around("pointCut()")
    public void around1(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("OrderTestAspect.around1:" + "around before");
//        joinPoint.proceed();
        System.out.println("OrderTestAspect.around1:" + "around after");
    }
    @After("pointCut()")
    public void after() {
        System.out.println("OrderTestAspect.after");
    }
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("OrderTestAspect.afterReturning");
    }
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("OrderTestAspect.afterThrowing");
    }
}测试
正常顺序
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
SimpleAspect.around1:around before
SimpleAspect.before
OrderTestAspect.around1:around before
OrderTestAspect.around1:around after
SimpleAspect.afterReturning
SimpleAspect.after
SimpleAspect.around1:around afterpostman结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}颠倒顺序(低优先级调用proceed())
postman访问:http://localhost:8080/user/print?id=321&userName=Tony¬e=abc
后端结果
OrderTestAspect.around1:around before
OrderTestAspect.around1:around afterpostman结果
{
    "id": 321,
    "userName": "Tony",
    "note": "abc"
}其他网址
《深入浅出Spring Boot 2.x》=> 4.3 AOP开发详解










