1 什么是AOP?
Aspect Oriented Programming ,即面向切面编程。
- AOP是对面向对象编程的一个补充;
- 它的目的是将复杂的需求分解为不同的切面,将散布在系统中的公共功能集中解决;
- 它的实际含义是在运行时将代码切入到类的指定方法、指定位置上,将不同方法的同一个位置抽象为一个切面对象,并对该对象进行编程。
下面是AOP的一个示意图

2 AOP的有点和概念
2.1 优点
- 降低模块之间的耦合度;
- 使系统更容易扩展;
- 更好的代码复用;
- 非业务代码更加集中,不分散,便于统一管理;
- 业务代码更加简洁纯粹,不掺杂其他的代码影响。
2.2 常见概念
- 切面:横切关注点,被模块化的抽象对象;
- 通知:切面对象完成的工作(非业务代码);
- 目标:被通知的对象(即被横切的对象);
- 代理:切面、通知、目标混合之后的对象;
- 连接点:通知要插入业务代码的具体位置(如Spring实现中的JoinPoint);
- 切点:AOP通过切点定位到连接点。
3 使用注解方式实现Spring AOP的使用
3.1 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.3.7.RELEASE</version>
</dependency>3.2 定义实体类,实现方法
3.3 添加切面(创建切面类)


/**
* @ClassName: DemoAspect
* @Description: 切面类
* @Date: 2022/9/21 9:00
*/
//Aspect注解声明了这是一个切面类
//Component注解把切面类交给了IoC容器进行管理
@Aspect
@Component
public class DemoAspect {
@Autowired
private DemoEntityService demoEntityService;
@Pointcut("execution( * com.demo.service.impl.DemoEntityServiceImpl.submitMain(..))"
+ "||execution( * com.demo.demo1.service.impl.Demo1EntityServiceImpl.saveInfo(..))"
+ "||execution( * com.demo.demo2.service.impl.Demo2EntityServiceImpl.submitReturnData(..))")
public void demoPointCut() {
}
/**
* @description 切点方法返回之后执行
* @date 2022/8/3 13:24
* AfterReturning中的pointcut这样写代表在submitMain、saveInfo、submitReturnData方法返回后都会执行doAfterReturning方法中的代码
**/
@AfterReturning(returning = "result", pointcut = "demoPointCut()")
public void doAfterReturning(Object result) throws Exception {
System.out.println("切点方法返回后执行");
demoEntityService.demoMethod(result);
}
/**
* @description 切点方法开始前执行
* @date 2022/8/3 13:24
* Before中的pointcut这样写代表在submitMain、saveInfo、submitReturnData方法返回后都会执行doAfterReturning方法中的代码
**/
@Before("demoPointCut()")
public void doBefore(JoinPoint joinPoint) throws Exception {
//joinPoint参数传递了方法的基本信息
System.out.println("切点方法开始前执行");
//获取方法名
//joinPoint.getSignature()获得方法的Method对象,随后的getName()获得方法名
String name = joinPoint.getSignature().getName();
//获取参数
//将参数数组转换为字符串
//joinPoint的getArgs()获得方法的参数列表,以String类型存储
String args = Arrays.toString(joinPoint.getArgs());
//切面要执行的非业务代码
System.out.println(name + "方法的参数是" + args);
}
/**
* @description 切点方法执行后执行
* @date 2022/8/3 13:24
* Before中的pointcut这样写代表在submitMain、saveInfo、submitReturnData方法返回后都会执行doAfterReturning方法中的代码
**/
@After("demoPointCut()")
public void doAfter(JoinPoint joinPoint) throws Exception {
//joinPoint参数传递了方法的基本信息
System.out.println("切点方法执行后执行");
//获取方法名
//joinPoint.getSignature()获得方法的Method对象,随后的getName()获得方法名
String name = joinPoint.getSignature().getName();
//切面要执行的非业务代码
System.out.println(name + "方法执行完毕");
}
//环绕增强
@Around("demoPointCut()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("前环绕");
//执行其切点方法
pjp.proceed();
System.out.println("后环绕");
}
}View Code
3.4 补充说明
3.4.1 AOP开发注解的类型
其中,通知的配置语法:@通知注解(“切点表达式")

各种增强的执行顺序分别是:
前环绕增强->前置增强->切点->后环绕增强->最终增强->后置增强
After和After-returning的区别:
后置通知(After):表示在目标方法执行完成后执行的通知功能,即使在执行目标方法出现异常,也照常执行这个逻辑。
返回通知(After-returning)表示目标方法正常执行完成后置的通知功能,如果目标方法执行过程中出现异常,那么这个通知的逻辑就不执行。
切点表达式的一个格式语法如下:
格式:execution( [修饰符] 返回值类型 包名.类名.方法名 (参数) ),其中*表示任意类型,方法参数中 . . 表示任意的参数。
示例:
execution(public void aop.TargetImpl.run()) 表示 aop.TargetImpl类,修饰符为public,返回值、参数列表为空的run方法。
execution(void aop.TargetImpl.*()) 表示 aop.TargetImpl类,返回值、参数列表为空的任意方法。
execution(* aop…*(…)) 表示 aop包及其子包下的任意类,任意方法。https://blog.51cto.com/u_14020810/4851474#_101Spring_AOP_582
















