AOP应用场景
- 场景一: 记录日志
- 场景二: 监控方法运行时间 (监控性能)
- 场景三: 权限控制
- 场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )
- 场景五: 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 ,如声明式事务)
AOP相关概念
- Aspect 切面 通常指@Aspect标识的类
- Join point 连接点 In Spring AOP, a join point always represents a method execution. 目标对象中的方法就是一个连接点
- Advice 通知 @Before、@AfterReturning、@AfterThrowing、@After、@Around
- Pointcut 切点 连接点的集合
- Introduction:引入,Declaring additional methods or fields on behalf of a type
- Target object:目标对象,原始对象
- AOP proxy:代理对象, 包含了原始对象的代码和增强后的代码的那个对象
- Weaving: 织入
编程范式
- 面向过程编程 C
- 面向对象编程 C++/Java
- 函数式编程
- 事件驱动编程
- 面向切面编程
AOP是什么
aop是一种编程范式,是oop的补充
aop应用场景
- 权限控制
- 缓存控制
- 事务控制
- 审计日志
- 性能监控
- 分布式追踪
- 异常处理
AOP的初衷
- 减少重复代码
- 关注点分离:功能性需求、非功能性需求
官方文档
代码
package com.fuzzy.search.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @author yanyugang
* @description 官方配置文档:
* https://docs.spring.io/spring/docs/5.1.13.BUILD-SNAPSHOT/spring-framework-reference/core.html#aop-ataspectj
* @date 2019-12-31 9:50
*/
@Aspect
@Component
public class LogAspect {
// 可以自定义注解,再需要拦截的地方加上自定义注解
// 切点表达式限制为包含指定注解RequestMapping的连接点(配置方式一)
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void cutPoint(){
}
@Around("cutPoint()")
public Object bizOnPoint(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("前置通知(@Before的作用)");
Object result=null;
try {
// Returns the arguments at this join point.
// 拦截的方法的参数
Object[] args=joinPoint.getArgs();
// 方法的相关信息,方法名等
Signature signature=joinPoint.getSignature();
// 全类名#方法名
String identity=joinPoint.getSignature().getDeclaringTypeName()
.concat("#").concat(joinPoint.getSignature().getName());
int modifiers=signature.getModifiers();
// 执行方法
result=joinPoint.proceed();
System.out.println("返回通知(@AfterReturning的作用)");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常通知(@AfterThrowing的作用)");
} finally {
System.out.println("后置通知(@After的作用)");
}
return result;
}
// 切点表达式限制为指定包路径com.fuzzy.search.controller下的任何类的任何方法(配置方式二)
@Pointcut("execution(* com.fuzzy.search.controller.*.*(..))")
public void myPoint(){
}
@Around("myPoint()")
public Object bizMyPoint(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("bizMyPoint");
System.out.println("前置通知(@Before的作用)");
Object result=null;
try {
result=joinPoint.proceed();
System.out.println("返回通知(@AfterReturning的作用)");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("异常通知(@AfterThrowing的作用)");
} finally {
System.out.println("后置通知(@After的作用)");
}
return result;
}
}