阅读这篇博文时,假定读者已经掌握了Spring Boot+maven开发应用的入门技巧,
初次接触Spring Boot,那也没关系,移步Spring Boot + maven 开发的入门教程,
10分钟完成你的第一个Spring Boot应用
1. 使用的核心技术
####动态代理
没有接触过设计模式的同学,请移步设计模式02-动态代理模式,
先了解动态代理设计模式,有助于理解Spring AOP的原理
2. Java Maven项目需要的pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3. 切面Aspect类定义
PointCut(切点)+Advice(通知)
package driver.aop;
import org.aspectj.lang.JoinPoint;
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.stereotype.Component;
@Component
@Aspect
public class WebControllerAop {
//匹配driver.controller包下的所有无参方法
// @Pointcut("execution(* driver.controller..*.*(..))")
public void executeService0() {
}
//匹配driver.controller.WebController类下的所有无参方法
@Pointcut("execution(* driver.controller..WebController.*())")
public void executeService() {
}
/**
* 前置通知,方法调用前被调用
*
* @param joinPoint
*/
@Before("executeService()")
public void doBeforeAdvice(JoinPoint joinPoint) {
System.out.println("Before通知");
}
// 方法体执行后,在方法return返回值前执行
@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint) {
System.out.println("After通知");
}
// 方法return返回值之后执行,需要对方法返回值做加工的可以用此通知
@AfterReturning(value="executeService()",returning="keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
System.out.println("AfterReturning通知");
}
//环绕通知,方法执行前后都可以增加处理逻辑,
//值得注意的是,环绕通知方法的切点必须用ProceedingJoinPoint
@Around("executeService()")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("环绕通知执行方法前");
try {// obj之前可以写目标方法执行前的逻辑
Object obj = proceedingJoinPoint.proceed();// 调用执行目标方法
System.out.println("环绕通知执行方法后");
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
}
4. 测试用的目标类定义
####1. driver.controller.WebController
package driver.controller;
import java.util.Map;
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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import driver.config.ConfigHelper;
import driver.service.BootService;
@Controller
public class WebController {
@RequestMapping(value="/ttt",method=RequestMethod.GET)
@ResponseBody
public String ttt(){
return "ttt";
}
}
运行main方法,启动Spring Boot,
浏览器访问 http://localhost:8080/ttt
运行结果:
- 浏览器会返回 ttt字符串
- 会输出如下日志
2. driver.controller.InterfaceController
package driver.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class InterfaceController {
/**
* @PathVariable
*/
@RequestMapping("/path/{name}/{age}")
@ResponseBody
public String getNames(@PathVariable("name")String a,@PathVariable("age")int age) {
//System.out.println("名字是:"+a+",年龄:"+age);
return "name:"+a+",age:"+age;
}
}
运行main方法,启动Spring Boot,
浏览器访问 http://localhost:8080/path/xiaoming/20
运行结果:
- 浏览器返回字符串: name:xiaoming,age:20
但是不会有上述截图的AOP相关日志
总结
使用Spring Boot开发应用时,通过Spring提供的AOP能力,
在执行跟切点匹配的方法时,能把通用的前置、后置处理跟具体的业务逻辑实现分离、解耦
举两个特别常用且有效的应用场景:
- 方法执行前后记日志
- 事务控制
本篇博文旨在引导读者基于Spring Boot使用AOP功能,
具体的知识点,如PointCut/Advice定义等,用到时自行查阅资料。