一.什么是AOP我们为什么要使用AOPAOPAspect-Oriented Programming中文是面向切面编程简单来说AOP的作用就是把多个方法中重复出现的公共功能提取出来统一管理在需要的时自动执行而不用在每个方法里面重复的编写这些代码。1.AOP和OOP面向对象的区别与联系对比OOP 面向对象编程AOP 面向切面编程主要关注对象、属性、业务行为多个模块共用的横向功能举例员工类、订单类、菜品类日志、事务、性能监控解决的问题如何组织业务代码如何统一处理重复的公共逻辑可以说AOP 是对 OOP 的补充。它主要用于处理多个模块中重复出现的横向关注点例如日志记录、事务管理和性能监控从而降低代码耦合提高代码复用性和可维护性。二.学习AOP的一些相关名词(学前铺垫理解1.切面Aspect:一个专门放置公共功能处理逻辑的模块。例如我们准备创建一个专门记录操作日志的类这个类就可以定义为一个切面。Aspect Component public class LogAspect { // 在这里编写日志处理逻辑 }解释一下代码Aspect告诉Spring,这个类是一个AOP切面Component:让Spring扫描并管理这个类使他成为Spring容器中的Bean2.连接点Join Point:程序执行过程中能够作为 AOP 介入位置的点。在 Spring AOP 中最常见的连接点就是 Spring Bean 的方法执行。例如employeeService.getEmployee() 类似这样方法的执行都可能成为AOP处理的连接点Aspect Component public class LogAspect { Before(execution(* com.example.service.*.*(..))) public void before(JoinPoint joinPoint) { // 获取正在执行的方法名称 String methodName joinPoint.getSignature().getName(); // 打印方法名称 System.out.println(即将执行的方法 methodName); // 获取方法传入的参数 Object[] args joinPoint.getArgs(); System.out.println(方法参数数量 args.length); } }JoinPoint最常见的几个方法方法作用getSignature()获取方法签名信息getSignature().getName()获取方法名称getArgs()获取方法传入的参数getTarget()获取实际的目标对象getThis()获取当前 AOP 代理对象3.切入点Pointcut:这么多方法我究竟要在哪些方法上执行 AOP就比如我只想给service层的业务方法记录日志但是不想给所有方法记录日志就可以通过切入点表达式来进行筛选Pointcut(execution(* com.qingda.tliaswebmanagement.service.*.*(..))) public void serviceMethods() { }4.通知Advice:在匹配到的方法执行过程中的什么时机运行哪段公共代码。Spring AOP 中常用的通知有五种:通知类型注解通俗理解前置通知Before业务方法执行之前后置通知After业务方法执行之后无论是否正常完成返回通知AfterReturning业务方法正常返回之后异常通知AfterThrowing业务方法抛出异常之后环绕通知Around可以控制目标方法执行前后还能决定何时调用目标方法5.目标对象Target:真正负责业务的对象例如EmployeeServiceImpl负责查询员工那么它就是目标对象。AOP 不会要求你把查询员工的业务代码搬到切面里。查询仍然由原来的业务对象完成。6.代理对象Proxy把切面和业务方法衔接起来原来调用的employeeService.getEmployee(); 表面上看是在调用员工服务的方法。但在 Spring AOP 中如果这个 Bean 被 AOP 增强Spring 通常会提供一个代理对象让调用先经过代理再由代理决定何时执行切面逻辑和真正的业务方法。就是controller调用service --代理对象Proxy负责衔接Aop和目标方法 -- 切面逻辑和目标方法按照通知类型和配置执行我回来了三.用实例来感受一下觉得这么说不太直观还是感觉太抽象怎么办上代码业务类Service public class EmployeeService { public void getEmployee() { System.out.println(正在查询员工信息...); } public void addEmployee() { System.out.println(正在新增员工...); } }切面类package com.example.demo.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; Aspect Component public class LogAspect { Around(execution(* com.example.demo.service.EmployeeService.*(..))) public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable { // 记录开始时间 long start System.currentTimeMillis(); // 执行真正的业务方法 Object result joinPoint.proceed(); // 记录结束时间 long end System.currentTimeMillis(); // 输出方法名称和执行耗时 System.out.println( joinPoint.getSignature().getName() 执行耗时 (end - start) 毫秒 ); return result; } }execution(* com.example.demo.service.EmployeeService.*(..))匹配EmployeeService类中的任意方法不限制返回类型和参数。*..这就意味着调用addEmployee()和deleteEmployee()时都会匹配这个规则。如果你只想增强某个方法可以缩小匹配范围。例如Around(execution(* com.example.demo.service.EmployeeService.addEmployee(..)))这样就只匹配addEmployee方法。