spring aop设计原理

AOP产生的背景:

想要为不同的对象引入一个公共行为,可能导致大量重复代码。如果使用aop,可能只需要关注如下红色框的业务逻辑(切面逻辑),就可以

什么是aop:有三个过程

找到横切点:确定程序在哪个位置进行横切

写横切逻辑:与aop无关,就是开发同学需要关注的业务代码

织入:将横切逻辑织入 横切点

 

横切点 分为 字段和方法。方法(构造方法,静态方法,对象方法)

 

目标一:找到横切点

定义一个横切点:

功能1是返回给用户当前的横切点;

  如果横切点作用在对象(对象方法,对象字段,构造函数),则需要返回AccessibleObject和当前对象,

  如果作用在类(静态方法),只需要返回accessibleObject

功能2是 是否需要在横切点控制多个横切逻辑的调用。可以框架支持,也可以由横切点控制。

  责任链模式的api设计。例如tomcat的Filter是 集合形式调用,netty的 handler组织是 链表形式调用

 

如果需要集合形式调用,则需要在横切点定义一个方法来链式调用。 JoinPoint 是集合形式调用

JoinPoint来确定横切点

public interface Joinpoint {

 Object proceed() throws Throwable;

 Object getThis();

 AccessibleObject getStaticPart();

}

  

 

 

目标二:横切逻辑(增强)抽象定义

增强,需要连接点信息,要投入到一个地方

 在MethodInterceptor,传入连接点信息(因为是方法拦截,所以这里是方法级别的连接点接口定义)

Object invoke(MethodInvocation invocation) throws Throwable;

 

目标三:织入

静态织入:采用自定义类加载机制。在加载时 偷梁换柱。

动态织入:动态代理(jdk proxy);动态字节码生成技术(cglib)

spring采用动态织入,生成的代理对象中,维护了当前连接点的所有拦截器,调用目标方式时,被代理类拦截,在代理类中做aop

完整流程图:

 

 

 = spring AOP的典型例子

// Aspect(切面类)—— AOP 思想的具体载体
@Aspect
@Component
public class LogAspect {
    // Pointcut(切入点):定义织入位置(所有com.service包下的方法)
    @Pointcut("execution(* com.service.*.*(..))")
    public void servicePointcut() {}

    // Advice(通知):织入逻辑(方法执行前打印日志)
    @Before("servicePointcut()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("执行方法前打印日志:" + joinPoint.getSignature().getName());
    }

   @Around("aaa()")
    public void around(JoinPoint joinPoint) {
  //业务方法执行前,判断是否有缓存,有直接返回;如果没有,则继续执行 业务方法,后面再缓存结果
HttpServletRequest request = getRequestArgs(joinPoint);
if (null != request) {
  //如果需要缓存=true,则先判断是否有缓存,如果有,则返回缓存;如果没有,则调用 proceed方法执行业务方法,然后缓存

}
return joinPoint.proceed();

  } }

 =

image

 

 

 

 参考自一篇极好的文章  https://mp.weixin.qq.com/s/YplYY4nDIAyDyweuHskaaQ

posted @ 2023-08-31 09:53  野鹤闲人  阅读(31)  评论(0)    收藏  举报