AOP思想应该怎么去理解!
Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
Target(目标对象):织入 Advice 的目标对象。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
以下仅代表个人理解
个人理解,Join point就是需要Advice的方法,而切面操作可能要对大量的类进行Advice,所以就要先声明这些所有的Join point,可以这么理解Pointcut切点是所有Join point连接点的集合,Join point 是Pointcut的真子集,Pointcut可以使用通配符,这样就降低Join point的声明成本,即没有Pontcut或者说Pointcut不是必须的,必须的是Join point,指代需要进行切面处理的方法
总结,Join point指代需要进行切面处理的方法,Pointcut是所有需要进行切面处理的方法,Advice是对方法进行的处理(即增强操作,与业务无关,如日志打印,全局异常拦截,统一返回值,多数据源的切换等)
个人认为最难理解的点可能就是命名,真是莫名其妙,我之前学习的时候就一直没搞明白切点,连接点,叫切线还差不多,线是点的集合,哈哈
要我命名的话,我要把Join point 命名为处理点handle point,Pointcut命名为切入点集(英文还没想好),Advice通知,叫这名也行,可以理解为通知Join point,要对其进行增强了,只能这么强行理解了
dependencies 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- aop 依赖, aspectj -->
<!-- 无此依赖,切面类无法声明,即无法使用@Aspect注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
controller
写一个简单的接口,能被外部访问就行
@Controller
@RequestMapping("/demo")
public class AopController {
@Autowired
private TestAopService testAopService;
@RequestMapping("/aop")
public void testAop() {
testAopService.testAop();
}
}
service
需要增强(插入与业务逻辑无关的代码)的类
@Service
@Slf4j
public class TestAopService {
public void testAop() {
log.info("test service start");
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.forEach(System.out::println);
log.info("test service end");
}
}
aspect
切面类,声明切面,并进行增强操作
//声明一个切面类,或者说将此类声明为切面
@Aspect
//要加上这个注解,才会注入到Spring容器,@Service及@Controller等都可理解为此注解的子注解
@Component
@Slf4j
public class TestAopServiceAspect {
//此方法相当于一个变量用来装execution(* com.java.aop.service.TestAopService.*(..))
//使用@Pointcut,现在才有点理解为啥切点是多个JontPoint了,因为此表达式是个通配的,说明可以在多处()起作用
@Pointcut("execution(* com.java.aop.service.TestAopService.*(..))")
public void pointcut(){};//此方法名称可以任意,比如test()或者aop(),当然对应的下面注解里的也要改
//@Around("execution(* com.java.aop.service.TestAopService.*(..)")
@Around("pointcut()")
//ProceedingJoinPoint 我的理解是正在执行的连接点,即方法调用,以此指代需要进行切面处理的方法
public void testAopHandle(ProceedingJoinPoint proceedingJoinPoint) {
log.info("aop start");
try {
proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
log.info("server error");
}
log.info("aop end");
}
}
浏览器访问: 未更改端口直接点击此链接
result
效果如下