AOP
面向切面编程,可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术
AOP的编程思想是把很多类对象中的横切问题点,从业务逻辑中分离出来,从而达到解耦的目的,增加代码的重用性,提高开发效率。
AOP的应用场景
- 日志记录
- 权限验证
- 事务处理
- 效率检查
- 异常处理
- 缓存处理
- 数据持久化
- 内容分发
Aspect概念
- aspect:切面,切面由切点和通知组成,即包括横切逻辑的定义也包括连接点的定义
- pointcut:切点,每个类都拥有多个连接点,可以理解是连接点的集合
- joinpoint:连接点,程序执行的某个特定位值,如某个方法调用前后等
- weaving:织入,将增强添加到目标类具体连接点的过程
- advice:通知,是织入到目标类连接点上的一段代码,就是增强到什么地方?增强什么内容?
- target:目标对象,通知织入的目标类
- aop Proxy:代理对象,即增强后产生的对象
Spring AOP 底层实现,是通过JDK动态代理或CGLIb代理在运行时期对象初始化阶段织入代码的。
JDK动态代理基于接口实现 | CGlib是基于类的继承实现 |
通知的种类
- Before advice :前置通知,在目标调用方法之前执行
- After advice:后置通知,在目标调用方法之后执行,目标方法没有异常
- After throwing adivce:异常通知,在目标方法抛出异常时执行
- After finally advice:最终通知,在目标方法执行后执行
- Around advice:环绕通知,最强大的通知类型,可以控制目标方法的执行(通过调用ProceedingJoinPoint.proceed()),可以在目标执行全过程中进行执行。
@Aspect
- 定义一个切面类Aspect
即声明类,增加@Component@Aspect两个注解,Springboot中要引用spring-boot-stater-aop依赖包 - 定义切点Pointcut
定义切点,并定义切点在那些地方执行,采用@Pointcut(public com.xxx.xxx..*(…)) - 定义Advice通知
利用通知的5种类型@Before,@After,@AfterReturning,@AfterThrowing,@Around来完成在某些切点的增强动作,如@Before(“myPointcut()”),myPointcut()为第二步定义的切面类
//1.定义切面
@Component
@AspectJ
public class LoggingAdvice {
private Logger logger =LoggerFactory.getLogger(LoggingAdvice.class);
}
//2.定义切点
@Pointcut(value ="execution(*com.controller.*.*(..))")
public void myPointcut(){
}
//3.定义Advice
//注意:ProceddingJointPoint只能用于环绕通知,因为ProceedingJointPoint暴露了proceed方法
@Around("myPointcut")
public Object applicationLogger(ProceddingJointPoint pjp)throw Throwable{
String methodName = pjp.getSignature().getName();
String className = pjp.getTarget().getClass().toString();
ObjectMapper m = new ObjectMapper();
Object[] array = pjp.getArgs();
logger.info("调用前:"+className+":"+methodName+"args="+m.writeValueAsString(array));
Object obj = ProceddingJointPoint.proceed();
logger.info("调用后:"+className+":"+methodName+"返回:"+m.writeValueAsString(obj));
return obj;
}