静态通知调用

静态通知调用

目录

  • 适配器模式:不同通知统一转换为环绕通知
  • 无参数绑定通知链执行过程,责任链模式体现
  • 模拟实现MethodInvocation

适配器模式

上一章的Main方法里面创建Advisors方法可以抽象为以下几个方法,分别对应不同的AspectJMethodxxxxAdvice,然后将不同通知统一转化为环绕通知MethodInterceptor。

        // 切面实例工厂
        AspectInstanceFactory factory = new SingletonAspectInstanceFactory(new A18Aspect());
        // 1. 获取相关通知
        List<Advisor> beforeAdvisors = getBeforeAdvisors(factory);
        List<Advisor> afterAdvisors = getAfterAdvisors(factory);
      // 2. 将相关通知统一转化为环绕通知MethodInterceptor
            A18Target target = new A18Target();

            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target);
            proxyFactory.addAdvisors(beforeAdvisors);

            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
            for (Object methodInterceptor : methodInterceptors) {
                System.out.println(methodInterceptor);
            }

为什么要转化

无论是ProxyFactory基于哪种方式创建代理,最后都要调用advice的都是MethodInvocation对象:
a. 因为Advisor有多个,且一个套一个调用,因此需要一个调用链对象,即MethodInvocation
b. MethodInvocation 要知道advice有哪些,还要知道目标,调用次序如下:

before1 -> before2 -> target -> after2 ->  after1

c. 从上图可以看出,环绕通知才适合作为advice,因此其他before,afterReturning,afterThrowing都会被转化为环绕通知
d. 统一转换为环绕通知,提现的是设计模式中的适配器模式

  • 对外是为了方便要区分before、afterReturing、afterThrowing
  • 对内都是使用环绕通知,统一使用MethodInterceptor表示

什么是适配器模式

以切面静态转换场景为例,通知会被转换为MethodInterceptor,而@Before这一类注解会被解析为AspectJMethodBeforeAdvice形式这样的另外一套接口。因此注解解析后的接口是不能直接使用的,我们需要把他统一转换为MethodInterceptor,而中间转换的类对象称之为适配器对象

org.springframework.aop.framework.adapter.AdvisorAdapter:

  1. MethodBeforeAdviceAdapter 将 @Before 的 AspectJMethodBeforeAdvice 适配为 MethodBeforeAdviceInterceptor
  2. AfterReturningAdviceAdapter 将 @AfterReturning AspectJAfterReturningAdvice 适配为 AfterReturningAdviceInterceptor

获取适配器的方式为:

            // 2. 将相关通知统一转化为环绕通知MethodInterceptor
            A18Target target = new A18Target();

            ProxyFactory proxyFactory = new ProxyFactory();
            // 准备把 MethodInvocation 放入通过advice的形式当前线程。(放在最外层)
            proxyFactory.addAdvice(0,ExposeInvocationInterceptor.INSTANCE);

            proxyFactory.setTarget(target);
            proxyFactory.addAdvisors(beforeAdvisors);

            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
            for (Object methodInterceptor : methodInterceptors) {
                System.out.println(methodInterceptor);
            }
           // 通过ProxyFactory.getInterceptorsAndDynamicInterceptionAdvice将相关通知统一转化为环绕通知MethodInterceptor
            A18Target target = new A18Target();

            ProxyFactory proxyFactory = new ProxyFactory();
            proxyFactory.setTarget(target);
            proxyFactory.addAdvisors(beforeAdvisors);

            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

            List<Object> methodInterceptors = proxyFactory.getInterceptorsAndDynamicInterceptionAdvice(A18Target.class.getMethod("foo"), A18Target.class);
            for (Object methodInterceptor : methodInterceptors) {
                System.out.println(methodInterceptor);
            }

调用链执行

            // 3. 创建执行调用链(组成:环绕通知s + 目标信息)
            // 3.1 准备调用链(package org.springframework.aop.framework;)
            MethodInvocation methodInvocation = new ReflectiveMethodInvocation(
                    null,
                    target,
                    A18Target.class.getMethod("foo"),
                    new Object[0],
                    A18Target.class,
                    methodInterceptors
            );
            // 3.2 调用调用链
            methodInvocation.proceed();

实现责任链模式:


public class A18_1 {

    static class A18_1Aspect {
        @Before("execution(* foo()) ")
        public void before() {
            System.out.println("before1");
        }

        @Before("execution (* foo())")
        public void before2() {
            System.out.println("before2");
        }

        public void after() {
            System.out.println("after");
        }

        public void afterReturning() {
            System.out.println("afterReturning");
        }
    }

    static class A18_1Target {
        public void foo() {
            System.out.println("target.foo");
        }
    }

    static class A18_1Advice1 implements MethodInterceptor {

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice1 before()");
            Object proceed = invocation.proceed();
            System.out.println("Advice1 after()");
            return proceed;
        }
    }

    static class A18_1Advice2 implements MethodInterceptor {

        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice2 before()");
            Object proceed = invocation.proceed();
            System.out.println("Advice2 after()");
            return proceed;
        }
    }

    /**
     * 1. 把必要信息存储在 invocation 中:target、
     * 2.
     */
    static class MyInvocation implements MethodInvocation {
        // 目标对象
        private Object target;
        // 目标方法
        private Method method;
        // 目标方法的参数
        private Object[] params;
        // 环绕通知的list
        private List<MethodInterceptor> methodInterceptorList;

        private int curInterceptorIndex = -1;

        public MyInvocation(Object target, Method method, Object[] params, List<MethodInterceptor> methodInterceptorList) {
            this.target = target;
            this.method = method;
            this.params = params;
            this.methodInterceptorList = methodInterceptorList;
        }

        @Override
        public Method getMethod() {
            return method;
        }

        @Override
        public Object[] getArguments() {
            return params;
        }

        @Override
        public Object proceed() throws Throwable {
            // 调用每一个环绕通知 和 目标
            if (curInterceptorIndex == methodInterceptorList.size() - 1) {
                return method.invoke(target, params);
            }
            MethodInterceptor curMethodInterceptor = methodInterceptorList.get(++this.curInterceptorIndex);
            return curMethodInterceptor.invoke(this);
        }

        @Override
        public Object getThis() {
            // 返回目标对象
            return target;
        }

        @Override
        public AccessibleObject getStaticPart() {
            // todo
            return method;
        }
    }


    public static void main(String[] args) throws Throwable {
        A18_1Target target = new A18_1Target();
        A18_1Advice1 advice1 = new A18_1Advice1();
        A18_1Advice2 advice2 = new A18_1Advice2();
        List<MethodInterceptor> methodInterceptors = Lists.newArrayList(advice2, advice1);
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target);
        MyInvocation invocation = new MyInvocation(
                target,
                A18_1Target.class.getMethod("foo"),
                new Object[0],
                methodInterceptors
        );
        invocation.proceed();
    }
}
posted @ 2023-01-25 19:53  SsoZh  阅读(24)  评论(0编辑  收藏  举报