1 创建项目
STS工具
file,new,spring starter project
2 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 http://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.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zfh</groupId>
<artifactId>springAOP-8</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springAOP-8</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 添加web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<!-- 添加aop支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3 核心业务
package com.fhzheng.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DoHomeWorkController {
@GetMapping("/dohomework")
public void doHomeWork(String name) {
System.out.println(name + "Method:做家庭作业,这是核心任务... ...");
}
}
4 切面1
package com.fhzheng.demo.aspect;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Order(1)
@Aspect
@Component
public class DoHomeWorkAspect {
/** 定义切入点 */
@Pointcut("execution(* com.fhzheng.demo.controller.DoHomeWorkController.doHomeWork(..))")
public void homeWorkPointcut() {
}
/** 定义Before advice通知类型处理方法 */
@Before("homeWorkPointcut()")
public void beforeHomeWork() {
ServletRequestAttributes requestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
System.out.println("Aspect1:Before "+request.getParameter("name") + "回家思考先要做什么事,想先吃个冰淇淋......");
}
/** 定义Around advice通知类型处理方法 */
@Around("homeWorkPointcut()")
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("Aspect1:Around 回家思考的环绕通知,方法执行前");
try {
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("Aspect1:Around 回家思考的环绕通知,方法执行后");
}
/** 定义AfterReturning advice通知类型处理方法 */
@AfterReturning("homeWorkPointcut()")
public void afterReturningHomeWork() {
System.out.println("Aspect1:AfterReturning 回家思考的正常返回后通知,方法执行后");
}
/** 定义After advice通知类型处理方法 */
@After("homeWorkPointcut()")
public void afterHomeWork() {
System.out.println("Aspect1:After 回家思考的最终返回后通知,方法执行后");
}
}
5 切面2
package com.fhzheng.demo.aspect;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Order(2)
@Aspect
@Component
public class DoHomeWorkPrepare {
/** 定义切入点 */
@Pointcut("execution(* com.fhzheng.demo.controller.*.*(..))")
public void prepare() {
}
/** 定义Before advice通知类型处理方法 */
@Before("prepare()")
public void beforeHomeWork() {
ServletRequestAttributes requestAttributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
System.out.println("Aspect2:Before "+request.getParameter("name") + "换上做清洁工作的套装......");
}
/** 定义Around advice通知类型处理方法 */
@Around("prepare()")
public void around(ProceedingJoinPoint joinPoint) {
System.out.println("Aspect2:Around 做清洁工作的环绕通知,方法执行前");
try {
joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("Aspect2:Around 做清洁工作的环绕通知,方法执行后");
}
/** 定义AfterReturning advice通知类型处理方法 */
@AfterReturning("prepare()")
public void afterReturningHomeWork() {
System.out.println("Aspect2:AfterReturning 清洁工作的正常返回后通知,方法执行后");
}
/** 定义After advice通知类型处理方法 */
@After("prepare()")
public void afterHomeWork() {
System.out.println("Aspect2:After 清洁工作的最终返回后通知,方法执行后");
}
}
6 运行

7 结果

8 一个个切面的执行顺序
Around–>Before–>Around–>After–>AfterReturning
–>AfterThrowing
9 多个切面的执行顺序


有点类似于过滤器的执行顺序

可以看到Aspect1 和Aspect2两个切面类中所有通知类型的执行顺序,Method是具体的切入点,order代表优先级,它根据一个int值来判断优先级的高低,数字越小,优先级越高!所以,不同的切面,实际上是环绕于切入点的同心圆:

在真实的业务应用中,切面有多个时,需要以实际跑出来的顺序为准啊。
SpringBoot AOP实践
1481

被折叠的 条评论
为什么被折叠?



