什么是aop
aop(Aspect Oriented Programming)面向切面编程,一种可以在运行时在被调用的方法前后动态织入代码的编程方式。
相关术语
- Aspect: 切面,包含一些Pointcut和Advice
- Pointcut:切入点,相当于一个条件,只有符合条件的方法才会走Advice
- advice:通知,只有符合Pointcut的方法会执行通知,advice分为before,around,after,AfterReturning,AfterThrowing
- advice通过以下几种通知来确定在什么时候调用advice
- @before:前置通知,方法执行之前调用advice
- @around:环绕通知,方法执行前后都会调用advice
- @after:后置通知,方法执行之后调用advice(无论方法执行是否发送异常,总是调用)
- @AfterReturning:后置通知,方法执行之后调用advice,可以获取返回值 (无论方法执行是否发送异常,总是调用)
- @AfterThrowing:后置通知,方法执行中发生异常后调用,可以获取异常信息(只有发生异常才会)
集成aop
- 新建一个springboot项目
- pom.xml中引入aop依赖
引入依赖
新建项目后,在pom.xml中引入aop依赖 spring-boot-starter-aop
,pom.xml完整依赖如下:
<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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
编写切面
/**
* @auther: chenmingyu
* @date: 2018/12/5 17:26
* @description:
*/
@Aspect
@Component
public class TestAspect {
/**
* 切入点
*/
@Pointcut("execution(public * com.my.aop.controller.*.*(..))")
public void execute(){
}
/**
* 前置通知
* @param joinPoint
*/
@Before(value ="execute()")
public void Before(JoinPoint joinPoint) {
System.out.println("执行方法之前");
}
/**
* 环绕通知
* @param proceedingJoinPoint
* @return
*/
@Around(value ="execute()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("环绕通知开始");
try {
System.out.println("执行方法:" + proceedingJoinPoint.getSignature().getName());
Object object = proceedingJoinPoint.proceed();
System.out.println("环绕通知结束,方法返回:" + object);
return object;
} catch (Throwable e) {
System.out.println("执行方法异常:" + e.getClass().getName());
return null;
}
}
/**
* 后置通知
* @param joinPoint
*/
@After(value ="execute()")
public void After(JoinPoint joinPoint) {
System.out.println("执行方法之后");
}
/**
* 后置通知,带返回值
* @param obj
*/
@AfterReturning(pointcut = "execute()",returning = "obj")
public void AfterReturning(Object obj) {
System.out.println("执行方法之后获取返回值:"+obj);
}
/**
* 后置通知,异常时执行
* @param e
*/
@AfterThrowing(throwing = "e",pointcut = "execute()")
public void doAfterThrowing(Exception e) {
System.out.println("执行方法异常:"+e.getClass().getName());
}
}
@Aspect :声明这个类是一个切面
@Component:将bean交由spring管理
@Pointcut(“execution(public * com.my.aop.controller..(..))”):声明切入点
execution(public * com.my.aop.controller..(..)):条件表达式,之后com.my.aop.controller包下的public声明的方法会走通知
@Before,@Around,@After,@AfterReturning,@AfterThrowing:通知类型
验证Aspect
/**
* @auther: chenmingyu
* @date: 2018/12/5 17:34
* @description:
*/
@RestController
public class AspectController {
/**
* 走切面
* @return
*/
@GetMapping("/test")
public String test(){
return "method return";
}
/**
* 不走切面
*/
@GetMapping("/test1")
private void test1(){
}
/**
* 走切面,抛异常
*/
@GetMapping("/throws")
public void throwsException(){
throw new RuntimeException();
}
}
执行 http://localhost:8080/test1,没有输出