使用递归算法+责任链模拟AOP底层通知调用

系列文章目录

SpringAOP实现

深入SpringAOP实现流程(源码分析)

使用递归算法+责任链模拟AOP底层通知调用



一、AOP通知

我们可以先看一个切面类

@Component
@Aspect//定义切面类
@EnableAspectJAutoProxy //开启AOP]
public class LogAOP {

    @Pointcut("execution(* com.spring.aop.service..*.*(..))")

    public void logAop() {

    }

    //前置通知

    /**
     * 方法执行前进行通知
     */
    @Before("logAop()")
    public void before() {
        System.out.println("【前置通知】");
    }

    //后置通知

    /**
     * 方法体执行完通知
     */
    @After("logAop()")
    public void after() {
        System.out.println("【后置通知】");
    }

    //运行通知

    /**
     * 运行通知和后置通知区别:
     * 后置执行完了再去进行运行通知
     * 当程序运行时有异常是不会去执行运行通知但是会执行后置通知
     */
    @AfterReturning("logAop()")
    public void AfterReturning() {
        System.out.println("【运行通知】");
    }

    //异常通知

    /**
     * 出现异常了就会进行通知
     */
    @AfterThrowing("logAop()")
    public void AfterThrowing() {
        System.out.println("【异常通知】");
    }

    //环绕通知
    @Around("logAop()")
    public void Around(ProceedingJoinPoint joinPoint) {
        try {
            System.out.println("【环绕通知】");//在方法之前执行
            joinPoint.proceed();
            System.out.println("【环绕通知】");//在方法之后执行
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

以上切面类中就体现了我们AOP的所有通知,那么这些通知在低层中如何调用的呢?我们先看一下通知结果然后我们再去手写模拟底层的一个通知

【环绕通知】
【前置通知】
【testMethod】
【环绕通知】
【后置通知】
【运行通知】

二、模拟AOP通知

1、包结构

在这里插入图片描述

  1. interceptor 是模拟通知的放的各种通知的共同方法和不同实现
  2. invocation 是模拟拼接调用链璐
  3. service 是模拟我们拦截的方法
  4. Test是测试类

2、interceptor

MethodInterceptor接口

public interface MethodInterceptor {
    /**
     * 定义共同通知的骨架
     */
    void invoke(MethodInvocation methodInvocation);
}

前置通知实现

public class BeforeMethodInterceptor implements MethodInterceptor {
    @Override
    public void invoke(MethodInvocation methodInvocation) {
        System.out.println("【前置通知】");
        methodInvocation.process();
    }
    //前置通知完成了执行目标方法

}

后置通知实现

public class AfterMethodInterceptor implements MethodInterceptor {
    @Override
    public void invoke(MethodInvocation methodInvocation) {
        //执行前置通知
        methodInvocation.process();
        System.out.println("【后置通知】");
    }
}

环绕通知实现

public class AroundMethodInterceptor implements MethodInterceptor {
    @Override
    public void invoke(MethodInvocation methodInvocation) {
        System.out.println("【目标方法之前环绕通知】");
        //执行前置通知
        methodInvocation.process();
        System.out.println("【目标方法之后环绕通知】");
    }
}

3、invocation

MethodInvocation接口

public interface MethodInvocation {
    void process();
}

MethodInvocation实现类

public class DefaultMethodInvocation implements MethodInvocation {
    /**
     * 存放所有通知
     */
    private List<MethodInterceptor> list;
    private Object target;//目标对象
    private Method method;//目标方法
    private Object args[];//目标参数
    //最终使用反射机制去执行方法

    private int index;

    public DefaultMethodInvocation(List<MethodInterceptor> list, Object target, Method method, Object[] args) {
        this.list = list;
        this.target = target;
        this.method = method;
        this.args = args;
    }

    /**
     * 建立调用链路
     */
    @Override
    public void process() {
        if (index == list.size()) {
            try {
                method.invoke(target, args); //执行目标方法
                return;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("【出现异常】");
            }
        }

        MethodInterceptor methodInterceptor = list.get(index++);
        methodInterceptor.invoke(this);
    }
}

4、service

public class TestService {
    public void test(String userName) {
        System.out.println("userName:" + userName);
    }
}

5、Test

public class Test {
  
    public static void main(String[] args) throws NoSuchMethodException {
        //1、装配通知
        List<MethodInterceptor> list = new ArrayList();

        list.add(new BeforeMethodInterceptor());
        list.add(new AfterMethodInterceptor());
        list.add(new AroundMethodInterceptor());
        //2、创建目标方法;
        TestService testService = new TestService();
        Method test = TestService.class.getMethod("test", String.class);
        Object[] params = {"瑞文"};
        new DefaultMethodInvocation(list, testService, test, params).process();


    }
}

6、运行结果

【前置通知】
【目标方法之前环绕通知】
测试方法
【目标方法之后环绕通知】
【后置通知】

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值