【0 -> Spring】AOP 学习笔记 (二)

AOP

1. 实现植入代码的链式调用。
  • 上一节的学习中。通过读取aop的配置文件已经实例化了一个Pointcut(AspectJExpressionPointcut),它被用来找到那些满足被植入条件的Method。以及MethodLocatingFactory,它被用来定位具体的切入Method(注意,这里的Method,不是Pointcut中的target method,而是具体植入代码的方法)。

  • 接下来很自然的就会想到,将MethodLocatingFactory中定位到的植入代码的Method与pointcut中找到的那些满足被植入条件的method结合起来,希望达到的效果是当我调用被植入method的时候,在执行它的之前、之后做一些具体的操作。

  • 植入代码的Method在AOP中是以MethodInterceptor的理念被实现的。在AOP alliance中,MethodInterceptor接口继承了Interceptor,进而Interceptor又继承了Advice。Advice仅仅是个空接口,仅表示实现了它的都是属于它Advice这个class。这样就很好理解了,在执行目标代码的时候,有什么对它要说的建议都要实现上述的接口。
    这里写图片描述

  • 上述图中具体的AspectJAfterReturnAdvice中包含了adviceMethod(具体植入代码的方法),pointcut,以及adviceObjectFatory(它来提供被植入代码的方法所属类的信息)。

  • 接下来需要一个调度类来结合被植入的MethodInterceptor和目标方法。Spring AOP中使用了ReflectiveMethodInvocation。如下图所示,ReflectiveMethodInvocation其实就是一个Jointpoint,实现了proceed方法,这是植入代码链式调用的核心,所以,没错ReflectiveMethodInvocation封装了一系列的MethodInterceptor。同时,ReflectiveMethodInvocation封装了目标方法,和目标类型,当然他们使用来调用原本的方法的。
    这里写图片描述
    这里写图片描述

  • 接下来看看ReflectiveMethodInvocation的核心方法,Proceed(),它实现自Jointpoint接口。在方法中,遍历地查看MethodInterceptor,然后调用interceptor的invoke方法,具体的AfterReturning, AfterThrowing, BeforeAdvice的方法就在这其中实现。调用invoke的同事,ReflectiveMethodInvocation会将自己作为参数传入,这样就实现了链式调用。其实结合起来看,ReflectiveMethodInvocation作为Jointpoint,它包含了目标方法,目标类型,目标方法参数以及拦截器
    这里写图片描述

  • 到此已经完成了advice注入jointpoint的链式调用。那么下一步,就是剩下动态得生成AOP proxy对象了。达到的效果就是,当调用某类的方法时候,调用的是他的子类即proxy类的方法。proxy类包含了一些列advices,目标方法,目标类型。Spring AOP中定义了,如下的AopProxyFactory创建proxy类。如图所示,得到一个proxy类,我们只需要给出相应的Advice(即Interceptor)和targetObject(即rootClass, proxy类继承于它)。CglibProxyFactory在实现AopProxyFactory接口方法getProxy时,会设置好Callback(Cglib中的Interceptor),callBack中通过AOPConfig中的advice的属性中的AspectJExpressionPointcut(上一章一开始实现的类,在这用到了)来匹配目标的Method。若匹配得上,则将advice加入Interceptor。
    这里写图片描述

Callback[] callbacks = getCallbacks(rootClass);

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {

        Callback aopInterceptor = new DynamicAdvisedInterceptor(this.config);

        //Callback targetInterceptor = new StaticUnadvisedExposedInterceptor(this.advised.getTargetObject());

        //Callback targetDispatcher = new StaticDispatcher(this.advised.getTargetObject());
        Callback[] callbacks = new Callback[] {
                aopInterceptor,  // AOP_PROXY for normal advice
                /*targetInterceptor,  // INVOKE_TARGET invoke target without considering advice, if optimized
                new SerializableNoOp(),  // NO_OVERRIDE  no override for methods mapped to this
                targetDispatcher,        //DISPATCH_TARGET
                this.advisedDispatcher,  //DISPATCH_ADVISED
                new EqualsInterceptor(this.advised),
                new HashCodeInterceptor(this.advised)*/
        };
        return callbacks;
    }

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
        private final AopConfig config;
        public DynamicAdvisedInterceptor(AopConfig advised) {
            this.config = advised;
        }
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {


            Object target = this.config.getTargetObject();


            List<Advice> chain = this.config.getAdvices(method/*, targetClass*/); // 通过在运行时调用匹配的Method
            Object retVal;
            // Check whether we only have one InvokerInterceptor: that is,
            // no real advice, but just reflective invocation of the target.
            if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                // We can skip creating a MethodInvocation: just invoke the target directly.
                // Note that the final invoker must be an InvokerInterceptor, so we know
                // it does nothing but a reflective operation on the target, and no hot
                // swapping or fancy proxying.
                retVal = methodProxy.invoke(target, args);
            }
            // 有匹配上的方法,拦截器不为空。
            else {
                List<org.aopalliance.intercept.MethodInterceptor> interceptors =
                        new ArrayList<org.aopalliance.intercept.MethodInterceptor>();

                interceptors.addAll(chain);


                // We need to create a method invocation...
                retVal = new ReflectiveMethodInvocation(target, method, args, interceptors).proceed();
            }
            //retVal = processReturnType(proxy, target, method, retVal);
            return retVal;

        }
    }
  • 最终在运行时调用方法时,会触发拦截器的匹配,然后对有匹配到的方法进行拦截,用ReflectiveMethodInvocation(即Jointpoint)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值