zoukankan      html  css  js  c++  java
  • Spring核心框架

    一、AOP的体系结构

    如下图所示:(引自AOP联盟)

    层次3语言和开发环境:基础是指待增加对象或者目标对象;切面通常包括对于基础的增加应用;配置是指AOP体系中提供的配置环境或者编织配置,通过该配置AOP将基础和切面结合起来,从而完成切面对目标对象的编织实现。

    层次2面向方面系统:配置模型,逻辑配置和AOP模型是为上策的语言和开发环境提供支持的,主要功能是将需要增强的目标对象、切面和配置使用AOP的API转换、抽象、封装成面向方面中的逻辑模型。

    层次1底层编织实现模块:主要是将面向方面系统抽象封装的AOP模型编织进待增强的目标对象的实现技术。

    二、AOP的原理

    AOP 代理其实是由 AOP 框架动态生成的一个对象,该对象可作为目标对象使用。AOP 代理包含了目标对象的全部方法,但 AOP 代理中的方法与目标对象的方法存在差异:AOP 方法在特定切入点添加了增强处理,并回调了目标对象的方法。

    Spring 的 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。

    纵观 AOP 编程,其中需要程序员参与的只有 3 个部分:
    定义普通业务组件。
    定义切入点,一个切入点可能横切多个业务组件。
    定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。

    上面 3 个部分的第一个部分是最平常不过的事情,无须额外说明。那么进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理,而 AOP 代理的方法大致有如下公式:

    代理对象的方法 = 增强处理 + 被代理对象的方法

    在上面这个业务定义中,不难发现 Spring AOP 的实现原理其实很简单:AOP 框架负责动态地生成 AOP 代理类,这个代理类的方法则由 Advice 和回调目标对象的方法所组成。

    简而言之:AOP 原理的奥妙就在于动态地生成了代理类。下面介绍使用 CGLIB 来生成代理类。

    CGLIB 来生成代理类

    CGLIB(Code Generation Library),简单来说,就是一个代码生成类库。它可以在运行时候动态是生成某个类的子类。

    此处使用前面定义的 Chinese 类,现在改为直接使用 CGLIB 来生成代理,这个代理类同样可以实现 Spring AOP 代理所达到的效果。

    下面先为 CGLIB 提供一个拦截器实现类:

    [html] view plaincopy
     
    1. public class AroundAdvice implements MethodInterceptor {  
    2.     public Object intercept(Object target, Method method, Object[] args,  
    3.             MethodProxy proxy) throws java.lang.Throwable {  
    4.         System.out.println("执行目标方法之前,模拟开始事务 ...");  
    5.         // 执行目标方法,并保存目标方法执行后的返回值  
    6.         Object rvt = proxy.invokeSuper(target, new String[] { "被改变的参数" });  
    7.         System.out.println("执行目标方法之后,模拟结束事务 ...");  
    8.         return rvt + " 新增的内容";  
    9.     }  
    10. }  

    上面这个 AroundAdvice.java 的作用就像前面介绍的 Around Advice,它可以在调用目标方法之前、调用目标方法之后织入增强处理。

    接下来程序提供一个 ChineseProxyFactory 类,这个 ChineseProxyFactory 类会通过 CGLIB 来为 Chinese 生成代理类:

    [html] view plaincopy
     
    1. public class ChineseProxyFactory {  
    2.     public static Chinese getAuthInstance() {  
    3.         Enhancer en = new Enhancer();  
    4.         // 设置要代理的目标类  
    5.         en.setSuperclass(Chinese.class);  
    6.         // 设置要代理的拦截器  
    7.         en.setCallback(new AroundAdvice());  
    8.         // 生成代理类的实例  
    9.         return (Chinese) en.create();  
    10.     }  
    11. }  

    上面粗体字代码就是使用 CGLIB 的 Enhancer 生成代理对象的关键代码,此时的 Enhancer 将以 Chinese 类作为目标类,以 AroundAdvice 对象作为“Advice”,程序将会生成一个 Chinese 的子类,这个子类就是 CGLIB 生成代理类,它可作为 Chinese 对象使用,但它增强了 Chinese 类的方法。

    CGLIB 生成的代理完全可以作为 Chinese 对象来使用,而且 CGLIB 代理对象的 sayHello()、eat() 两个方法已经增加了事务控制(只是模拟),这个 CGLIB 代理其实就是 Spring AOP 所生成的 AOP 代理。

    这就是 Spring AOP 的根本所在:Spring AOP 就是通过 CGLIB 来动态地生成代理对象,这个代理对象就是所谓的 AOP 代理,而 AOP 代理的方法则通过在目标对象的切入点动态地织入增强处理,从而完成了对目标方法的增强。

    三、Spring AOP的底层实现常用类

    分析Spring AOP的底层实现首先要从ProxyConfig类开始,ProxyConfig是所有产生Spring AOP代理对象的基类,它是一个数据类,主要为其AOP代理对象工厂实现类提供配置属性。根据ProxyConfig的继承体系分析创建AOP代理常用类的作用:

    (1)AdvisedSupport是ProxyConfig的子类,它封装了AOP中对通知(Advice)和通知器(Advisor)的相关操作,这些操作对于不同的AOP的代理对象的生成都是一样的,但对于具体的AOP代理对象的创建,AdvisedSupport把它交给子类去实现。

    (2)ProxyCreatorSupport是AdvisedSupport的子类,它是其子类创建AOP代理对象的一个辅助类,提供不同AOP代理对象生成的通用操作,具体的AOP代理对象生成,由ProxyCreatorSupport的子类完成。

    (3)创建AOP代理对象的类:

    ProxyCreatorSupport有3个子类,分别创建不同的AOP代理对象,具体如下:

    a.AspectJProxyFactory:主要用于创建AspectJ的AOP应用,起到集成Spring和AspectJ的作用。

    b.ProxyFactory:创建编程式的Spring AOP应用。

    c.ProxyFactoryBean:创建声明式的Spring AOP应用。

    四、Spring AOP代理源码解析

    1、声明式Spring AOP代理工厂对象ProxyFactoryBean:

    我们以ProxyFactoryBean为例,分析Spring AOP的实现原理,ProxyFactoryBean是Spring中一个非常灵活的创建AOP应用的底层方法,封装了AOP的主要功能。

    一个简单的AOP代理工厂对象的配置如下:

    [html] view plaincopy
     
    1. <!--配置通知器,通知器的实现定义了需要对目标对象进行的增强行为-->  
    2. <bean id=”testAdvisor” class=”com.test.TestAdvisor”/>  
    3. <!--配置AOP代理,封装AOP功能的主要类-->  
    4. <bean id=”testAOP” class=”org.springframework.aop.ProxyFactoryBean”>  
    5.     <!--AOP代理接口-->  
    6.     <property name=”proxyInterfaces”>  
    7.         <value>com.test.TestProxyInterface</value>  
    8.     </property>  
    9.     <!--需要使用AOP切面增强的对象-->  
    10.     <property name=”target”>  
    11.         <bean class=”com.test.TestTarget”/>  
    12.     </property>  
    13.     <!--代理拦截器,配置通知器的名称,即通知器在AOP代理的配置下通过使用代理对象的拦截机制发挥作用-->  
    14.     <property name=”interceptorNames”>  
    15.         <list>  
    16.             <value>testAdvisor</value>  
    17.         </list>  
    18.     </property>  
    19. </bean>  

    2、ProxyFactoryBean生成AOP Proxy代理对象:

    从上面的ProxyFactoryBean的简单配置例子我们可以看出,ProxyFactoryBean是用来配置目标对象和切面行为Advice的,ProxyFactoryBean通过其配置的拦截器名称interceptorNames即通知器Advisor将切面行为Advice应用到目标对象中。

    在ProxyFactoryBean中,需要为待增强目标对象目标对象生成Proxy代理对象,从而为AOP切面的编织提供基础,下面通过源码分析ProxyFactoryBean的生成AOPProxy代理对象的实现过程:

    (1)ProxyFactoryBean产生代理对象的主要源码:

    [html] view plaincopy
     
    1. public class ProxyFactoryBean extends ProxyCreatorSupport  
    2.         implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {  
    3. //标注通知器器为全局通用通知器  
    4. public static final String GLOBAL_SUFFIX = "*";  
    5. //标志通知器链是否已经完成初始化  
    6. private boolean advisorChainInitialized = false;  
    7. //单态模式对象  
    8. private Object singletonInstance;  
    9. ……  
    10. //ProxyFactoryBean创建AOPProxy代理的入口方法  
    11. public Object getObject() throws BeansException {  
    12.         //初始化通知器链  
    13.         initializeAdvisorChain();  
    14.         //如果目标对象是单态模式  
    15.         if (isSingleton()) {  
    16.             //调用获取单态模式对象的方法产生AOPProxy代理  
    17.             return getSingletonInstance();  
    18.         }  
    19.         //如果目标对象是原型模式  
    20.         else {  
    21.             if (this.targetName == null) {  
    22.                 logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +  
    23.                         "Enable prototype proxies by setting the 'targetName' property.");  
    24.             }  
    25.             //调用原型模式对象方法每次创建一个新的AOPProxy代理对象  
    26.             return newPrototypeInstance();  
    27.         }  
    28.     }  
    29. //初始化通知器链  
    30. private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {  
    31.     //如果通知器链已经被初始化,则直接返回,即通知器链只在第一次获取代理对象时产生  
    32.         if (this.advisorChainInitialized) {  
    33.             return;  
    34.         }  
    35.         //如果ProxyFactoryBean中配置的连接器列名名称不为空  
    36.         if (!ObjectUtils.isEmpty(this.interceptorNames)) {  
    37.             //如果没有Bean工厂(容器)  
    38.             if (this.beanFactory == null) {  
    39.                 throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +  
    40.                         "- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));  
    41.             }  
    42.             //全局通知器不能是通知器链中最后一个,除非显式使用属性指定了目标  
    43.             if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&  
    44.                     this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {  
    45.                 throw new AopConfigException("Target required after globals");  
    46.             }  
    47.             //遍历通知器链,向容器添加通知器  
    48.             for (String name : this.interceptorNames) {  
    49.                 if (logger.isTraceEnabled()) {  
    50.                     logger.trace("Configuring advisor or advice '" + name + "'");  
    51.                 }  
    52.                 //如果通知器是全局的  
    53.                 if (name.endsWith(GLOBAL_SUFFIX)) {  
    54.                     if (!(this.beanFactory instanceof ListableBeanFactory)) {  
    55.                         throw new AopConfigException(  
    56.                                 "Can only use global advisors or interceptors with a ListableBeanFactory");  
    57.                     }  
    58.                     //向容器中添加全局通知器  
    59.                     addGlobalAdvisor((ListableBeanFactory) this.beanFactory,  
    60.                             name.substring(0, name.length() - GLOBAL_SUFFIX.length()));  
    61.                 }  
    62.                 //如果通知器不是全局的  
    63.                 else {  
    64.                     Object advice;  
    65.                     //如果通知器是单态模式  
    66.                     if (this.singleton || this.beanFactory.isSingleton(name)) {  
    67.                         //从容器获取单态模式的通知或者通知器  
    68.                         advice = this.beanFactory.getBean(name);  
    69.                     }  
    70.                     //如果通知器是原型模式  
    71.                     else {  
    72.                         //创建一个新的通知或者通知器对象  
    73.                         advice = new PrototypePlaceholderAdvisor(name);  
    74.                     }  
    75.                     //添加通知器  
    76.                     addAdvisorOnChainCreation(advice, name);  
    77.                 }  
    78.             }  
    79.         }  
    80.         //设置通知器链已初始化标识  
    81.         this.advisorChainInitialized = true;  
    82.     }  
    83. //获取一个单态模式的AOPProxy代理对象  
    84. private synchronized Object getSingletonInstance() {  
    85.         //如果单态模式的代理对象还未被创建  
    86.         if (this.singletonInstance == null) {  
    87.             //获取代理的目标源  
    88.             this.targetSource = freshTargetSource();  
    89.             //如果ProxyFactoryBean设置了自动探测接口属性,并且没有配置代理接  
    90.             //且不是目标对象的直接代理类  
    91.             if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {  
    92.                 //获取代理对象的目标类  
    93.                 Class targetClass = getTargetClass();  
    94.                 if (targetClass == null) {  
    95.                     throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");  
    96.                 }  
    97.             //设置代理对象的接口 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));  
    98.             }  
    99.     //初始化共享的单态模式对象                   super.setFrozen(this.freezeProxy);  
    100.     //调用ProxyFactory生成代理AOPProxy对象  
    101.             this.singletonInstance = getProxy(createAopProxy());  
    102.         }  
    103.         return this.singletonInstance;  
    104.     }  
    105. //获取一个原型模式的代理对象  
    106. private synchronized Object newPrototypeInstance() {  
    107.         if (logger.isTraceEnabled()) {  
    108.             logger.trace("Creating copy of prototype ProxyFactoryBean config: " + this);  
    109.         }  
    110.         //根据当前的AOPProxyFactory获取一个创建代理的辅助类  
    111.         ProxyCreatorSupport copy = new ProxyCreatorSupport(getAopProxyFactory());  
    112.         //获取一个刷新的目标源  
    113.         TargetSource targetSource = freshTargetSource();  
    114.         //从当前对象中拷贝AOP的配置,为了保持原型模式对象的独立性,每次创建代理  
    115. //对象时都需要拷贝AOP的配置,以保证原型模式AOPProxy代理对象的独立性  
    116.         copy.copyConfigurationFrom(this, targetSource, freshAdvisorChain());  
    117.         if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {  
    118.             //设置代理接口  
    119.             copy.setInterfaces(  
    120.     ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));  
    121.         }  
    122.         copy.setFrozen(this.freezeProxy);  
    123.         if (logger.isTraceEnabled()) {  
    124.             logger.trace("Using ProxyCreatorSupport copy: " + copy);  
    125.         }  
    126.         //调用ProxyFactory生成AOPProxy代理  
    127.         return getProxy(copy.createAopProxy());  
    128.     }  
    129. //使用createAopProxy方法返回的AOPProxy对象产生AOPProxy代理对象  
    130. protected Object getProxy(AopProxy aopProxy) {  
    131.         return aopProxy.getProxy(this.proxyClassLoader);  
    132.     }  
    133. ……  
    134. }  

    通过源码分析,我们了解到AOPProxyFactory实现了FactoryBean接口,所以本身也是一个Spring的工厂Bean,AOP代理工厂的主要功能概况为:

    a.初始化通知器链,将配置的通知器链添加到容器存放通知/通知器的集合中。

    b.根据单态模式/原型模式,获取AOPProxy产生AOPProxy代理对象。

    (2)AOP创建辅助器(AOPCreatorSupport)获取AOP Proxy代理对象:

    AOP ProxyFactory的getSingletonInstance和newPrototypeInstance方法均通过调用AOPCreatorSupport的createAopProxy()方法获取AOP Proxy,主要源码如下:

    [html] view plaincopy
     
    1. public class ProxyCreatorSupport extends AdvisedSupport {  
    2. //AOPProxy工厂  
    3. private AopProxyFactory aopProxyFactory;  
    4. //当第一个AOPProxy代理对象被创建时,设置为true  
    5. private boolean active = false;  
    6. public AopProxyFactory getAopProxyFactory() {  
    7.         return this.aopProxyFactory;  
    8.     }  
    9. //默认使用DefaultAopProxyFactory作用AOP代理工厂  
    10. public ProxyCreatorSupport() {  
    11.         this.aopProxyFactory = new DefaultAopProxyFactory();  
    12.     }  
    13. //创建AOPProxy代理的入口方法  
    14. protected final synchronized AopProxy createAopProxy() {  
    15.         if (!this.active) {  
    16.             activate();  
    17.         }  
    18.         //调用DefaultAopProxyFactory的创建AOPProxy代理的方法  
    19.         return getAopProxyFactory().createAopProxy(this);  
    20.     }   
    21. //激活AOP代理配置,向容器注册代理回调监听器,第一次创建AOP代理时调用  
    22. private void activate() {  
    23.         this.active = true;  
    24.         for (AdvisedSupportListener listener : this.listeners) {  
    25.             listener.activated(this);  
    26.         }  
    27.     }   
    28. ……  
    29. }  

    通过对ProxyCreatorSupport的源码分析,我们知道真正创建AOPProxy代理对象的是DefaultAopProxyFactory类。

    (3)DefaultAopProxyFactory创建AOP Proxy代理对象:

    DefaultAopProxyFactory是AOP创建辅助器(AOPCreatorSupport)默认的AOP代理工厂,DefaultAopProxyFactory的createAopProxy方法实现了创建AOP代理的功能,源码如下:

    [html] view plaincopy
     
    1. public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {  
    2. //判断CGLIB类库是否在classpath中  
    3. private static final boolean cglibAvailable =  
    4.             ClassUtils.isPresent("net.sf.cglib.proxy.Enhancer", DefaultAopProxyFactory.class.getClassLoader());  
    5. //创建AOP代理对象  
    6. public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {  
    7.         //如果AOP使用显式优化,或者配置了目标类,或者只使用Spring支持的代理接口  
    8.         if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {  
    9.             //获取AOP配置的目标类  
    10.             Class targetClass = config.getTargetClass();  
    11.             if (targetClass == null) {  
    12.                 throw new AopConfigException("TargetSource cannot determine target class: " +  
    13.                         "Either an interface or a target is required for proxy creation.");  
    14.             }  
    15.             //如果配置的AOP目标类是接口,则使用JDK动态代理机制来生成AOP代理  
    16.             if (targetClass.isInterface()) {  
    17.                 return new JdkDynamicAopProxy(config);  
    18.             }  
    19.             //如果AOP配置的目标类不是接口,则使用CGLIB的方式来生成AOP代理  
    20.             if (!cglibAvailable) {  
    21.                 throw new AopConfigException(  
    22.                         "Cannot proxy target class because CGLIB2 is not available. " +  
    23.                         "Add CGLIB to the class path or specify proxy interfaces.");  
    24.             }  
    25.             return CglibProxyFactory.createCglibProxy(config);  
    26.         }  
    27.         else {  
    28.             return new JdkDynamicAopProxy(config);  
    29.         }  
    30.     }  
    31. //判断AOP是否只配置了SpringProxy代理接口或者没有配置任何代理接口  
    32.     private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {  
    33.         //获取AOP配置的所有AOP代理接口  
    34.         Class[] interfaces = config.getProxiedInterfaces();  
    35.         return (interfaces.length == 0 || (interfaces.length == 1 && SpringProxy.class.equals(interfaces[0])));  
    36.     }  
    37. }  

    通过对DefaultAopProxyFactory的源码分析,我们了解了Spring在创建AOP代理对象时,如果配置的目标类是接口,则使用JDK的动态代理机制来生成AOP代理,如果使用的不是接口,则使用CGLIB方式来生成AOP的动态代理。

    3、JDK动态代理机制创建AOPProxy代理对象:

    JDK的动态代理机制只能对接口起作用,即如果要对一个对象使用JDK动态代理方式生成代理对象时,该对象必须实现接口,Spring中通过JdkDynamicAopProxy类使用JDK动态代理机制生成AOPProxy代理对象,JdkDynamicAopProxy的主要源码如下:

    [html] view plaincopy
     
    1. final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {  
    2. ……  
    3. //JdkDynamicAopProxy的构造方法  
    4.     public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {  
    5.         Assert.notNull(config, "AdvisedSupport must not be null");  
    6.         //获取AOPBeanFactory中配置的通知器链和目标源  
    7.         if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {  
    8.             throw new AopConfigException("No advisors and no TargetSource specified");  
    9.         }  
    10.         //为当前对象设置AOP配置  
    11.         this.advised = config;  
    12.     }  
    13.     //获取AOP代理对象的入口方法  
    14.     public Object getProxy() {  
    15.         return getProxy(ClassUtils.getDefaultClassLoader());  
    16.     }  
    17.     //创建AOP代理对象  
    18.     public Object getProxy(ClassLoader classLoader) {  
    19.         if (logger.isDebugEnabled()) {  
    20.             logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());  
    21.         }  
    22.         //获取AOPBeanFactory中配置的代理接口  
    23.         Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);  
    24.         //查找代理目标的接口中是否定义equals()和hashCode()方法  
    25.         findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);  
    26.         //使用JDK的动态代理机制创建AOP代理对象  
    27.         return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  
    28.     }  
    29.     //查找给定类或接口中是否定义了equals()和hashCode()方法  
    30.     private void findDefinedEqualsAndHashCodeMethods(Class[] proxiedInterfaces) {  
    31.         //遍历给定的类/接口数组  
    32.         for (Class proxiedInterface : proxiedInterfaces) {  
    33.             //或者给定类/接口中所有声明的方法  
    34.             Method[] methods = proxiedInterface.getDeclaredMethods();  
    35.             //遍历类/接口中的声明的方法  
    36.             for (Method method : methods) {  
    37.                 //如果方法是equals()方法,则设置当前对象equalsDefined属性  
    38.                 if (AopUtils.isEqualsMethod(method)) {  
    39.                     this.equalsDefined = true;  
    40.                 }  
    41. //如果方法是hashCode()方法,则设置当前对象hashCodeDefined属性  
    42.                 if (AopUtils.isHashCodeMethod(method)) {  
    43.                     this.hashCodeDefined = true;  
    44.                 }  
    45.                 if (this.equalsDefined && this.hashCodeDefined) {  
    46.                     return;  
    47.                 }  
    48.             }  
    49.         }  
    50.     }  
    51. //AOP代理对象的回调方法  
    52.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
    53.         MethodInvocation invocation;  
    54.         Object oldProxy = null;  
    55.         boolean setProxyContext = false;  
    56.         //获取通知的目标源  
    57.         TargetSource targetSource = this.advised.targetSource;  
    58.         Class targetClass = null;  
    59.         Object target = null;  
    60.         try {  
    61.             //如果代理目标对象的接口中没有定义equals()方法,且当前调用的方法  
    62. //是equals()方法,即目标对象没有自己实现equals()方法  
    63.             if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {  
    64.                 return equals(args[0]);  
    65.             }  
    66.             //如果代理目标对象的接口中没有定义hashCode()方法,且当前调用的方法  
    67. //是hashCode()方法,即目标对象没有自己实现hashCode()方法  
    68.             if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {  
    69.                 return hashCode();  
    70.             }  
    71.             //如果AOP配置了通知,使用反射机制调用通知的同名方法  
    72.             if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&             method.getDeclaringClass().isAssignableFrom(Advised.class)) {  
    73.                 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);  
    74.             }  
    75.             Object retVal;  
    76.         //如果当前通知暴露了代理,则将当前代理使用currentProxy()方法变为可用代理  
    77.             if (this.advised.exposeProxy) {  
    78.                 oldProxy = AopContext.setCurrentProxy(proxy);  
    79.                 setProxyContext = true;  
    80.             }  
    81.             //获取目标对象  
    82.             target = targetSource.getTarget();  
    83.             if (target != null) {  
    84.                 targetClass = target.getClass();  
    85.             }  
    86.             //获取目标对象方法配置的拦截器(通知器)链  
    87.             List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  
    88.             //如果没有配置任何通知  
    89.             if (chain.isEmpty()) {  
    90.                 //没有配置通知,使用反射直接调用目标对象的方法,并获取方法返回值  
    91.                 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);  
    92.             }  
    93.             //如果配置了通知  
    94.             else {  
    95.             //为目标对象创建方法回调对象,需要在调用通知之后才调用目标对象的方法  
    96.                 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);  
    97.                 //调用通知链,沿着通知器链调用所有配置的通知  
    98.                 retVal = invocation.proceed();  
    99.             }  
    100.             //如果方法有返回值,则将代理对象最为方法返回  
    101.             if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&  
    102.                     !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {  
    103.                 retVal = proxy;  
    104.             }  
    105.             return retVal;  
    106.         }  
    107.         finally {  
    108.             if (target != null && !targetSource.isStatic()) {  
    109.                 //释放目标对象  
    110.                 targetSource.releaseTarget(target);  
    111.             }  
    112.             if (setProxyContext) {  
    113.                 //存储代理对象  
    114.                 AopContext.setCurrentProxy(oldProxy);  
    115.             }  
    116.         }  
    117.     }  
    118. ……  
    119. }  

    通过上述源码分析,我们看到JdkDynamicAopProxy本身实现了InvocationHandler接口和invoke()方法,JDK的动态代理机制的工作原理是:当调用目标对象的方法时,不是直接调用目标对象,而是首先生成一个目标对象的动态代理对象,触发代理对象的invoke()方法,代理的invoke()方法才会真正调用目标对象的方法。Spring AOP的实现原理是在代理对象invoke()方法调用目标对象的方法时,调用配置的通知。

    4、CglibProxyFactory创建AOP Proxy代理:

    JDK的动态代理只能针对接口生成代理对象,对于没有实现接口的目标对象,必须通过第3方的CGLIB来生成代理对象,CglibProxyFactory创建AOPProxy代理的主要源码如下:

    [html] view plaincopy
     
    1. //通过CGLIB方式创建AOP代理对象  
    2. public Object getProxy(ClassLoader classLoader) {  
    3.         if (logger.isDebugEnabled()) {  
    4.             logger.debug("Creating CGLIB2 proxy: target source is " + this.advised.getTargetSource());  
    5.         }  
    6.         try {  
    7.             //从代理创建辅助类中获取在IoC容器中配置的目标对象  
    8.             Class rootClass = this.advised.getTargetClass();  
    9.             Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");  
    10.             //将目标对象本身做为自己的基类  
    11.             Class proxySuperClass = rootClass;  
    12.             //检查获取到的目标类是否是CGLIB产生的  
    13.             if (AopUtils.isCglibProxyClass(rootClass)) {  
    14.                 //如果目标类是有CGLIB产生的,获取目标类的基类  
    15.                 proxySuperClass = rootClass.getSuperclass();  
    16.                 //获取目标类的接口  
    17.                 Class[] additionalInterfaces = rootClass.getInterfaces();  
    18.                 //将目标类的接口添加到容器AOP代理创建辅助类的配置中  
    19.                 for (Class additionalInterface : additionalInterfaces) {  
    20.                     this.advised.addInterface(additionalInterface);  
    21.                 }  
    22.             }  
    23.             //校验代理基类  
    24.             validateClassIfNecessary(proxySuperClass);  
    25.             //配置CGLIB的Enhancer类,Enhancer是CGLIB中的主要操作类  
    26.             Enhancer enhancer = createEnhancer();  
    27.             if (classLoader != null) {  
    28.                 enhancer.setClassLoader(classLoader);  
    29.                 if (classLoader instanceof SmartClassLoader &&  
    30.                         ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {  
    31.                     enhancer.setUseCache(false);  
    32.                 }  
    33.             }  
    34.             //设置enhancer的基类  
    35.             enhancer.setSuperclass(proxySuperClass);  
    36.             enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));  
    37.     //设置enhancer的接口 enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));  
    38.             enhancer.setInterceptDuringConstruction(false);  
    39.             //设置enhancer的回调方法  
    40.             Callback[] callbacks = getCallbacks(rootClass);  
    41.             enhancer.setCallbacks(callbacks);  
    42.             //将通知器中配置作为enhancer的方法过滤  
    43.             enhancer.setCallbackFilter(new ProxyCallbackFilter(  
    44.                     this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));  
    45.             Class[] types = new Class[callbacks.length];  
    46.             for (int x = 0; x < types.length; x++) {  
    47.                 types[x] = callbacks[x].getClass();  
    48.             }  
    49.             //设置enhancer的回调类型  
    50.             enhancer.setCallbackTypes(types);  
    51.             //创建代理对象  
    52.             Object proxy;  
    53.             if (this.constructorArgs != null) {  
    54.                 proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);  
    55.             }  
    56.             else {  
    57.                 proxy = enhancer.create();  
    58.             }  
    59.             return proxy;  
    60.         }  
    61.         catch (CodeGenerationException ex) {  
    62.             throw new AopConfigException("Could not generate CGLIB subclass of class [" +  
    63.                     this.advised.getTargetClass() + "]: " +  
    64.                     "Common causes of this problem include using a final class or a non-visible class",  
    65.                     ex);  
    66.         }  
    67.         catch (IllegalArgumentException ex) {  
    68.             throw new AopConfigException("Could not generate CGLIB subclass of class [" +  
    69.                     this.advised.getTargetClass() + "]: " +  
    70.                     "Common causes of this problem include using a final class or a non-visible class",  
    71.                     ex);  
    72.         }  
    73.         catch (Exception ex) {  
    74.             // TargetSource.getTarget() failed  
    75.             throw new AopConfigException("Unexpected AOP exception", ex);  
    76.         }  
    77.     }  
    78. //获取给定类的回调通知  
    79.  private Callback[] getCallbacks(Class rootClass) throws Exception {  
    80.         //优化参数  
    81.         boolean exposeProxy = this.advised.isExposeProxy();  
    82.         boolean isFrozen = this.advised.isFrozen();  
    83.         boolean isStatic = this.advised.getTargetSource().isStatic();  
    84.         //根据AOP配置创建一个动态通知拦截器,CGLIB创建的动态代理会自动调用  
    85.         //DynamicAdvisedInterceptor类的intercept方法对目标对象进行拦截处理  
    86.         Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);  
    87.         Callback targetInterceptor;  
    88.         //根据是否暴露代理,创建直接应用目标的通知  
    89.         if (exposeProxy) {  
    90.             targetInterceptor = isStatic ?  
    91.                     new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :  
    92.                     new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());  
    93.         }  
    94.         else {  
    95.             targetInterceptor = isStatic ?  
    96.                     new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :  
    97.                     new DynamicUnadvisedInterceptor(this.advised.getTargetSource());  
    98.         }  
    99.         // 创建目标分发器  
    100.         Callback targetDispatcher = isStatic ?  
    101.                 new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();  
    102.         Callback[] mainCallbacks = new Callback[]{  
    103.             aopInterceptor, //普通通知  
    104.             targetInterceptor, // 如果优化则不考虑配置的通知  
    105.             new SerializableNoOp(), //没有被覆盖的方法  
    106.             targetDispatcher, this.advisedDispatcher,  
    107.             new EqualsInterceptor(this.advised),  
    108.             new HashCodeInterceptor(this.advised)  
    109.         };  
    110.         Callback[] callbacks;  
    111.         //如果目标是静态的,并且通知链被冻结,则使用优化AOP调用,直接对方法使用  
    112. //固定的通知链  
    113.         if (isStatic && isFrozen) {  
    114.             Method[] methods = rootClass.getMethods();  
    115.             Callback[] fixedCallbacks = new Callback[methods.length];  
    116.             this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);  
    117.             for (int x = 0; x < methods.length; x++) {  
    118.                 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);  
    119.                 fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(  
    120.                         chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());  
    121.                 this.fixedInterceptorMap.put(methods[x].toString(), x);  
    122.             }  
    123.             //将固定回调和主要回调拷贝到回调数组中  
    124.             callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];  
    125.             System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);  
    126.             System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);  
    127.             this.fixedInterceptorOffset = mainCallbacks.length;  
    128.         }  
    129.         //如果目标不是静态的,或者通知链不被冻结,则使用AOP主要的通知  
    130.         else {  
    131.             callbacks = mainCallbacks;  
    132.         }  
    133.         return callbacks;  
    134.     }  

    通过上面对CGLIB创建代理和获取回答通知的源码分析,我们了解到CGLIB在获取代理的通知时,会创建DynamicAdvisedInterceptor类,当应用调用目标对象的方法时,不是直接调用目标对象,而是通过CGLIB创建的代理对象来调用目标对象,在调用目标对象的方法时,触发DynamicAdvisedInterceptor的intercept回调方法对目标对象进行处理,CGLIB回调拦截器链的源码如下:

    [html] view plaincopy
     
    1. //CGLIB回调AOP拦截器链  
    2. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
    3.             Object oldProxy = null;  
    4.             boolean setProxyContext = false;  
    5.             Class targetClass = null;  
    6.             Object target = null;  
    7.             try {  
    8.                 //如果通知器暴露了代理  
    9.                 if (this.advised.exposeProxy) {  
    10.                     //设置给定的代理对象为要被拦截的代理                                          oldProxy = AopContext.setCurrentProxy(proxy);  
    11.                     setProxyContext = true;  
    12.                 }  
    13.                 //获取目标对象  
    14.                 target = getTarget();  
    15.                 if (target != null) {  
    16.                     targetClass = target.getClass();  
    17.                 }  
    18.                 //获取AOP配置的通知  
    19.                 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);  
    20.                 Object retVal;  
    21.                 //如果没有配置通知  
    22.                 if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {  
    23.                     //直接调用目标对象的方法  
    24.                     retVal = methodProxy.invoke(target, args);  
    25.                 }  
    26.                 //如果配置了通知  
    27.                 else {  
    28.                     //通过CglibMethodInvocation来启动配置的通知  
    29.                     retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();  
    30.                 }  
    31.                 //获取目标对象对象方法的回调结果,如果有必要则封装为代理  
    32.                 retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal);  
    33.                 return retVal;  
    34.             }  
    35.             finally {  
    36.                 if (target != null) {  
    37.                     releaseTarget(target);  
    38.                 }  
    39.                 if (setProxyContext) {  
    40.                     //存储被回调的代理  
    41.                     AopContext.setCurrentProxy(oldProxy);  
    42.                 }  
    43.             }  
    44.         }  

    5、目标对象方法的调用:

    (1)JdkDynamicAopProxy直接调用目标对象方法:

    JdkDynamicAopProxy中是通过AopUtils.invokeJoinpointUsingReflection方法来直接调用目标对象的方法,源码如下:

    [html] view plaincopy
     
    1. //通过反射机制直接调用目标对象方法  
    2. public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)  
    3.             throws Throwable {  
    4.         try {  
    5. //通过反射使给定的方法可以访问,主要是对protected和private方法使用,//取消严格访问控制权限的限制  
    6.             ReflectionUtils.makeAccessible(method);  
    7.             //使用反射机制调用目标对象的方法  
    8.             return method.invoke(target, args);  
    9.         }  
    10.         catch (InvocationTargetException ex) {  
    11.             throw ex.getTargetException();  
    12.         }  
    13.         catch (IllegalArgumentException ex) {  
    14.             throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +  
    15.                     method + "] on target [" + target + "]", ex);  
    16.         }  
    17.         catch (IllegalAccessException ex) {  
    18.             throw new AopInvocationException("Could not access method [" + method + "]", ex);  
    19.         }  
    20.     }  

    (2)Cglib2AopProxy直接调用目标对象方法:

    Cglib2AopProxy是通过methodProxy.invoke来直接调用目标对象的方法,主要源码如下:

    retVal = methodProxy.invoke(target, args);

  • 相关阅读:
    菜鸟合作伙伴日志接入规范之C#实现
    使用JS在textarea在光标处插入内容
    ASP.NET MVC API 接口验证
    CSS3 grayscale滤镜+SVG使图片变黑白实例页面
    .NET MVC 获取 当前请求的 控制器/视图/区域 的名字
    asp.net 后台获取flv视频地址进行播放【转】
    实现输出h264直播流的rtmp服务器 flash直播服务器【转】
    如何实现一个c/s模式的flv视频点播系统
    视频流服务器配置[windows平台][转]
    小计
  • 原文地址:https://www.cnblogs.com/downey/p/4888451.html
Copyright © 2011-2022 走看看