Spring---AOP原理浅析

1、综述

AOP有些特有的概念,如:advisor、advice和pointcut等等,使用或配置起来有点绕,让人感觉有些距离感,其实它的实现就是一组标准的设计模式的组合使用:Factory、Proxy、Chain of Responsibility,只要搞清楚这几个设计模式,读AOP的源码是比较容易的。


首先看看ProxyFactoryBean这个类,这是AOP使用的入口,从AOP拿到的bean object就是ProxyFactoryBean.getObject得到的,从这条线下去,发现AOP就是通过Proxy模式从实际要执行的target做了包装,而Proxy还不止一套方案,通过Factory封装了两套Proxy实现方案:JDK 动态Proxy和Cglib Proxy。有两套实现主要是因为JDK 动态Proxy必须要target实现某个接口,如果不满足这个条件就会用Cglib增强字节码的方式来实现proxy。


2、Spring AOP实现的基本线索
我们选择ProxyFactoryBean作为入口点和分析的开始。ProxyFactoryBean是在Spring IoC环境中,创建AOP应用的最底层方法,从中,可以看到一条实现AOP的基本线索。
所有的逻辑从以下的方法开始,我们主要针对单例的代理对象的生成:


下面我们深入到SpringAOP核心代码的内部,看看代理对象的生成机制,拦截器横切逻辑以及织入的实现。

2.1 代理对象的生成

对于getSingletonInstance()方法返回了什么,这就是代理对象如何产生的逻辑了,然我们须根溯源,看看传说中的proxy到底是如何一步一步的产生的。

ProxyFactoryBean是AdvisedSupport的子类,Spring使用AopProxy接口把AOP代理的实现与框架的其他部分分离开来。在AdvisedSupport中通过这样的方式来得到AopProxy,当然这里需要得到AopProxyFactory的帮助 ,从JDK或者cglib中得到想要的代理对象:


这个DefaultAopProxyFactory是Spring用来生成AopProxy的地方,它包含JDK和Cglib两种实现方式。让我接着往里面看:


可以看到其中的代理对象可以由JDK或者Cglib来生成,JdkDynamicAopProxy类和Cglib2AopProxy都实现的是AopProxy的接口,我们进入JdkDynamicAopProxy实现中看看Proxy是怎样生成的:


用Proxy包装target之后,通过ProxyFactoryBean得到对其方法的调用就被Proxy拦截了, ProxyFactoryBean的getObject()方法得到的实际上是一个Proxy了,target对象已经被封装了。对 ProxyFactoryBean这个工厂bean而言,其生产出来的对象是封装了目标对象的代理对象。


2.2 拦截器的作用
前面分析了SpringAOP实现中得到Proxy对象的过程,接下来我们去探寻Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的。
还记得在JdkDynamicAopProxy中生成Proxy对象的时候,有一句这样的代码吗?
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
这里我们的JdkDynamicAopProxy实现了InvocationHandler这个接口,this参数对应的是InvocationHandler对象,也就是说当 Proxy对象的函数被调用的时候,InvocationHandler的invoke方法会被作为回调函数调用:



上面所说的目标对象方法的调用,是通过AopUtils的方法调用,使用反射机制来对目标对象的方法进行的:


接下来,我们来看具体的ReflectiveMethodInvocation中proceed()方法的实现,也就是拦截器链的实现机制:


从上面的分析我们看到了Spring AOP拦截机制的基本实现,比如Spring怎样得到Proxy,怎样利用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。


通过看JdkDynamicAopProxy.invoke的源码会发现,Spring AOP的各种花招是通过Chain of Responsibility模式串起来的,先看看一个标准的Chain of Responsibility是什么样子,看下面的类图:


而Chain of Responsibility的关键在于Invocation与Interceptor的配合,主要原则就两条:

1)Invocation需要维护Interceptor集合和游标,每次调用invoke时需要先调用游标所在的Interceptor.invoke,如果游标已超过最后一个Interceptor,则调用实际target的方法

2)Interceptor的invoke中除了要执行自己的拦截逻辑,还要通过Invocation.invoke把调用传递下去,拦截的灵活性就体现在Invocation.invoke执行与否和执行的顺序。

以上逻辑通过时序图来看,如下图所示:


理解Chain of Responsibility后再来看Spring AOP,JdkDynamicAopProxy.invoke做的事情就是以上Client做的事情,

1)首先通过this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);组装interceptor chain

2)然后new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);得到invocation

3)最后通过invocation.proceed();启动责任链


2.3 织入的实现
在上面调用拦截器的时候,经过一系列的注册,适配的过程以后,拦截器在拦截的时候,会调用到预置好的一个通知适配器,设置通知拦截器,这是一系列Spring设计好为通知服务的类的一个,是最终完成通知拦截和实现的地方,例如对 MethodBeforeAdviceInterceptor的实现是这样的:


可以看到通知适配器将advice适配成Interceptor以后,会调用advice的before方法去执行横切逻辑。这样就成功的完成了before通知的织入。


参考来源:

Spring源码学习(二)------ AOP

Spring AOP介绍及源码分析


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值