AOP
AOP(Aspect Oriented Programming)即面向切面编程。底层是通过动态代理去实现的,有接口则用 JDK 代理,没有则用 CGlib 代理。AOP 通常用于重复性工作,如:日志记录、事务、安全等。
合适的利用 AOP 可以降低代码耦合度。
概念
- 切面(Aspect):一个模块具有一组提供横切需求的 APIs
- 连接点(JoinPoint):执行过程中的某一点,也就是某一个被执行的操作(方法)
- 通知(Advice):对于连接点的通知
- 前置通知(Before):在 PointCut 之前执行
- 后置通知(After):在 PointCut 之后执行
- 返回后通知(After Return):在 PointCut 正常执行完之后执行,不抛出异常
- 环绕通知(Around):包围 PointCut 的通知
- 异常通知(After Throwing)在 PointCut 执行中抛出异常执行
- 切入点(PointCut):这是一组一个或多个连接点,通知应该被执行。切面中的所有通知所注意的连接点都由切入点表达式决定。
- 目标对象(Target Object):被通知的对象
使用 AOP 的两种方式
- XML:传统的AOP配置方式
- Annotation:现在都是使用Spring Boot,基本都是使用注解的形式配置 AOP,方便、强大
// 组件
@Component
// 切面
@Aspect
public class MappingAspect {
/**
* 切点,切所有 com.eternal 包
*/
@Pointcut("execution(* com.eternal.controller..*(..) )")
public void pointCut() {
}
@Before("pointCut()")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知——before():" + joinPoint);
}
@After("pointCut()")
public void after(JoinPoint joinPoint) {
System.out.println("后置置通知——before():" + joinPoint);
}
@Around("pointCut()")
public Object around(JoinPoint joinPoint) {
try {
System.out.println("环绕通知——around():" + joinPoint);
Object proceed = ((ProceedingJoinPoint) joinPoint).proceed();
System.out.println("环绕通知++++around():" + joinPoint);
return proceed;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
@AfterReturning("pointCut()")
public void afterReturning(JoinPoint joinPoint) {
System.out.println("返回后通知——afterReturning():" + joinPoint);
}
@AfterThrowing(value = "pointCut()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Throwable e) {
System.out.println("异常通知——afterThrowing():" + joinPoint);
e.printStackTrace();
}
}
环绕通知——around():execution(ResultVo com.eternal.controller.PermissionController.getPermissionById(String))
前置通知——before():execution(ResultVo com.eternal.controller.PermissionController.getPermissionById(String))
环绕通知++++around():execution(ResultVo com.eternal.controller.PermissionController.getPermissionById(String))
后置置通知——before():execution(ResultVo com.eternal.controller.PermissionController.getPermissionById(String))
返回后通知——afterReturning():execution(ResultVo com.eternal.controller.PermissionController.getPermissionById(String))
总结
Spring AOP 底层是由 观察者模式 加 代理模式 实现。在 IOC 容器初始化时,由 BeanPostProcesspr (Bean后置处理器) 开始,他是一个监听器,负责监听 Bean 的生命周期事件。 当 AOP 触发时,监听器收到消息随后创建 AOP 代理对象,如果代理对接有接口则用JDK创建,没有则用 CGlib 创建。 在调用方法的过程中,里面增加了拦截器,这个拦截器负责了方法调用生命周期的拦截和处理,也就是 AOP 通知的各种触发控制。