`
jsycjacky
  • 浏览: 11445 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Spring-AOP-2:CGLIB的动态代理

 
阅读更多

这篇文章紧接着上一篇静态代理和动态代理来说

前言:

到现在呢,老是讲动态代理,有的人都晕了,会说你这代理中用到的类怎么没有一个是与spring相关的呢,所以,我要说明的事,虽然现在讲的都是最普通的动态代理,但实质上就是将AOP的内部实现原理,Spring AOP之所以这么强大是因为它底层都是用动态代理来实现的,为了说明这一点,得贴出点源码来

1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理 
在spring的资源包中,找到org.springframework.aop.framework.JdkDynamicAopProxy这个类,在资源包的位置为spring-framework-2.5.6\src\org\springframework\aop\framework\JdkDynamicAopProxy.java,看看其中重要的代码片段

 

Java代码  收藏代码
  1. <span style="font-size: medium;"public Object getProxy(ClassLoader classLoader) {     
  2.         if (logger.isDebugEnabled()) {     
  3.             Class targetClass = this.advised.getTargetSource().getTargetClass();     
  4.             logger.debug("Creating JDK dynamic proxy" +     
  5.                     (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));     
  6.         }     
  7.         Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);     
  8.         return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);     
  9.     }  </span>  

 

再看org.springframework.aop.framework.ReflectiveMethodInvocation中的代码片段

 

Java代码  收藏代码
  1. <span style="font-size: medium;">public Object proceed() throws Throwable {     
  2.         //  We start with an index of -1 and increment early.     
  3.         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {     
  4.             return invokeJoinpoint();     
  5.         }     
  6.     
  7.         Object interceptorOrInterceptionAdvice =     
  8.             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);     
  9.         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {     
  10.             // Evaluate dynamic method matcher here: static part will already have     
  11.             // been evaluated and found to match.     
  12.             InterceptorAndDynamicMethodMatcher dm =     
  13.                 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;     
  14.             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {     
  15.                 return dm.interceptor.invoke(this);     
  16.             }     
  17.             else {     
  18.                 // Dynamic matching failed.     
  19.                 // Skip this interceptor and invoke the next in the chain.     
  20.                 return proceed();     
  21.             }     
  22.         }     
  23.         else {     
  24.             // It's an interceptor, so we just invoke it: The pointcut will have     
  25.             // been evaluated statically before this object was constructed.     
  26.             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);     
  27.         }     
  28.     }    
  29. </span>  

 

 

2.如果是没有接口声明的类呢?SPRING通过CGLIB包和内部类来实现 

Java代码  收藏代码
  1. <span style="font-size: medium;">private static class StaticUnadvisedInterceptor implements MethodInterceptor, Serializable {  
  2.   
  3.         private final Object target;  
  4.   
  5.         public StaticUnadvisedInterceptor(Object target) {  
  6.             this.target = target;  
  7.         }  
  8.   
  9.         public Object intercept(Object proxy, Method method, Object[] args,  
  10.                 MethodProxy methodProxy) throws Throwable {  
  11.   
  12.             Object retVal = methodProxy.invoke(target, args);  
  13.             return massageReturnTypeIfNecessary(proxy, target, retVal);  
  14.         }  
  15.     }  
  16.   
  17.   
  18.     /** 
  19.      * Method interceptor used for static targets with no advice chain, when the 
  20.      * proxy is to be exposed. 
  21.      */  
  22.     private static class StaticUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {  
  23.   
  24.         private final Object target;  
  25.   
  26.         public StaticUnadvisedExposedInterceptor(Object target) {  
  27.             this.target = target;  
  28.         }  
  29.   
  30.         public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
  31.             Object oldProxy = null;  
  32.             try {  
  33.                 oldProxy = AopContext.setCurrentProxy(proxy);  
  34.                 Object retVal = methodProxy.invoke(target, args);  
  35.                 return massageReturnTypeIfNecessary(proxy, target, retVal);  
  36.             }  
  37.             finally {  
  38.                 AopContext.setCurrentProxy(oldProxy);  
  39.             }  
  40.         }  
  41.     }  
  42.   
  43.   
  44.     /** 
  45.      * Interceptor used to invoke a dynamic target without creating a method 
  46.      * invocation or evaluating an advice chain. (We know there was no advice 
  47.      * for this method.) 
  48.      */  
  49.     private class DynamicUnadvisedInterceptor implements MethodInterceptor, Serializable {  
  50.   
  51.         public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
  52.             Object target = advised.getTargetSource().getTarget();  
  53.             try {  
  54.                 Object retVal = methodProxy.invoke(target, args);  
  55.                 return massageReturnTypeIfNecessary(proxy, target, retVal);  
  56.             }  
  57.             finally {  
  58.                 advised.getTargetSource().releaseTarget(target);  
  59.             }  
  60.         }  
  61.     }  
  62.   
  63.   
  64.     /** 
  65.      * Interceptor for unadvised dynamic targets when the proxy needs exposing. 
  66.      */  
  67.     private class DynamicUnadvisedExposedInterceptor implements MethodInterceptor, Serializable {  
  68.   
  69.         public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {  
  70.             Object oldProxy = null;  
  71.             Object target = advised.getTargetSource().getTarget();  
  72.             try {  
  73.                 oldProxy = AopContext.setCurrentProxy(proxy);  
  74.                 Object retVal = methodProxy.invoke(target, args);  
  75.                 return massageReturnTypeIfNecessary(proxy, target, retVal);  
  76.             }  
  77.             finally {  
  78.                 AopContext.setCurrentProxy(oldProxy);  
  79.                 advised.getTargetSource().releaseTarget(target);  
  80.             }  
  81.         }  
  82.     }</span>  

 

好了,已经知道spring内部实现就是动态代理机制了,所以现在我们手动写的关于CGLIB的动态代理还是要写个小示例的。

上一篇文章中如果ServiceImpl没有实现任何接口的话,那么创建代理对象就不能使用javax.lang.Proxy这个类了,这时需要使用CGLIB了,在spring资源包中找到CGLIB的jar:spring-framework-2.5.6\lib\cglib\cglib-nodep-2.1_3.jar

然后写一个新的代理实现类CGlibProxyFactory.java

 

Java代码  收藏代码
  1. <span style="font-size: medium;">package com.javacrazyer.dao;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import net.sf.cglib.proxy.Enhancer;  
  6. import net.sf.cglib.proxy.MethodInterceptor;  
  7. import net.sf.cglib.proxy.MethodProxy;  
  8.   
  9. public class CGlibProxyFactory implements MethodInterceptor {  
  10.     private Object targetObject;  
  11.   
  12.     public Object newProxy(Object targetObject) {  
  13.         this.targetObject = targetObject;  
  14.         Enhancer enhancer = new Enhancer();  
  15.         enhancer.setSuperclass(this.targetObject.getClass());  
  16.         enhancer.setCallback(this);  
  17.         // 返回代理对象  
  18.         return enhancer.create();  
  19.     }  
  20.   
  21.     /** 
  22.      * proxy 带来对象本身 method 被拦截到的方法 args 方法的参数 methodProxy 方法的代理对象 
  23.      */  
  24.     public Object intercept(Object proxy, Method method, Object[] args,  
  25.             MethodProxy methodProxy) throws Throwable {  
  26.         checkSecurity();  
  27.         Object ret = null;  
  28.         try {  
  29.             // 调用目标对象的真实方法  
  30.             ret = method.invoke(this.targetObject, args);  
  31.             // ret接受存在的返回值,不存在返回值则为Null  
  32.         } catch (Exception e) {  
  33.             e.printStackTrace();  
  34.         }  
  35.         return ret;  
  36.     }  
  37.   
  38.     public void checkSecurity() {  
  39.         System.out.println("--------ServiceImpl.checkSecurity()----------");  
  40.     }  
  41.   
  42. }  
  43. </span>  

 

 

这时测试类有所变化

Java代码  收藏代码
  1. <span style="font-size: medium;">package com.javacrazyer.dao;  
  2.   
  3. public class TestProxy {  
  4.     public static void main(String[] args) {  
  5.         CGlibProxyFactory hander = new CGlibProxyFactory();  
  6.         //创建代理对象,这是这个代理对象是UserManagerImpl的子类  
  7.           ServiceImpl  service = (ServiceImpl)hander.newProxy(new ServiceImpl());  
  8.           service.outPut();  
  9.           service.putOut();  
  10.     }  
  11. }  
  12. </span>  

 

 输出结果

--------ServiceImpl.checkSecurity()----------
I am method outPut
--------ServiceImpl.checkSecurity()----------
I am method putOut

 

到目前位置,无论是前面的静态代理,javax.lang.Proxy的动态代理,还是这里的CGLIB的动态代理都是没有借助任何框架的情况下实现AOP的方法

分享到:
评论

相关推荐

    spring-aop.xsd

    Spring AOP通过代理模式实现这一目标,支持动态代理(基于JDK)和CGLIB代理(对于无接口的类)。 `spring-aop.xsd`包含了不同版本(2.5、3.1、3.2)的XML配置元素和属性定义,这意味着随着Spring框架的版本更新,...

    spring-aop.jar

    1. **AOP代理**:Spring AOP支持两种代理方式,即JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于未实现接口的类。spring-aop.jar包含了这些代理机制的相关类,如`org.springframework.aop....

    spring-aop-4.0.0.RELEASE

    - **代理模式**:Spring AOP通过两种代理方式实现,即JDK动态代理和CGLIB代理。前者适用于接口实现类,后者适用于无接口的类。 - **注解驱动**:从4.0.0.RELEASE开始,Spring AOP支持完全基于注解的配置,大大...

    spring-aop-4.2.6.RELEASE.zip

    3. **智能代理增强**:Spring AOP可以自动创建JDK动态代理或CGLIB代理,根据目标对象是否实现了接口来决定,这使得AOP能在各种情况下无缝工作。 4. **事务管理**:Spring AOP在事务管理方面有着出色的表现,可以...

    spring-cglib-repack-3.2.0.jar和spring-objenesis-repack-2.1.jar

    总的来说,`spring-cglib-repack-3.2.0.jar`和`spring-objenesis-repack-2.1.jar`是Spring框架正常运行的关键组成部分,它们分别负责动态子类生成和无参构造函数对象的快速实例化,对于理解和优化Spring应用的性能有...

    spring-cglib-repack-3.2.5.jar,spring-objenesis-repack-2.6.ja及ck-2.5.1.jar

    "spring-cglib-repack-3.2.5.jar"、"spring-objenesis-repack-2.6.jar"和"spring-objenesis-repack-2.5.1.jar"这三个文件是Spring源码阅读环境中常用的依赖包,它们各自承担着不同的功能。 首先,我们来看"CGLIB"...

    spring-cglib-repack-3.2.5.jar,spring-objenesis-repack-2.6.jar

    标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是Spring框架在运行时依赖的两个关键库,它们主要涉及到动态代理和对象创建的优化。 1. **CGLIB(Code Generation Library)**: ...

    spring-cglib-repack-3.2.6.jar和spring-objenesis-repack-2.6.jar

    在提供的文件中,我们看到了两个与Spring相关的库:`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`。这两个库都是Spring框架的重要组成部分,用于解决特定的编程问题。 首先,让我们来了解...

    spring-cglib-repack-3.2.6.jar,spring-objenesis-repack-2.6.jarspring-cglib-repack

    总的来说,`spring-cglib-repack-3.2.6.jar` 和 `spring-objenesis-repack-2.6.jar`是Spring框架的核心组成部分,它们提供了代理和对象实例化的底层支持。在进行Spring源码学习或开发时,确保这两个库的正确引入是至...

    spring-boot aop

    默认情况下,Spring使用基于Java的代理,但对于需要在静态方法或非Spring管理对象上应用AOP的情况,可能需要使用CGLIB或AspectJ字节码代理。 5. **理解代理行为**:理解Spring AOP代理的工作方式很重要,因为这可能...

    3.2版本Spring源码需要源码所需要的jar:spring-asm-repack-5.0.4.jar,spring-cglib-repack-3.1.jar

    Spring-asm-repack和Spring-cglib-repack是Spring框架为了实现动态代理和增强类功能所使用的库。 ASM是一个Java字节码操控和分析框架,它可以直接生成和修改类的字节码。在Spring中,ASM主要用于AOP(面向切面编程...

    spring-cglib-repack-3.2.5.jar和spring-objenesis-repack-2.6.jar

    标题中的"spring-cglib-repack-3.2.5.jar"和"spring-objenesis-repack-2.6.jar"是两个与Spring框架相关的库文件,它们主要用于Spring框架的内部实现,尤其是针对Java对象的创建和代理机制。下面将详细解释这两个库的...

    spring-aop-annotation-log-all

    com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar spring-aspects-4.1.2.RELEASE.jar spring-web-4.1.2.RELEASE.jar /...

    spring-cglib-repack-3.2.4.jar和spring-objenesis-repack-2.5.1.jar

    在实际开发中,`spring-cglib-repack-3.2.4.jar`和`spring-objenesis-repack-2.5.1.jar`是Spring框架运行的必要组件,特别是对于那些使用AOP特性的项目。确保这两个jar包的正确引入,能有效避免因缺少依赖而导致的...

    Spring-Aop所有jar

    在Spring框架中,AOP通过代理模式实现,可以是JDK动态代理或者CGLIB代理。 首先,我们需要理解AOP的基本概念。切面(Aspect)是包含关注点的模块化单元,它封装了跨越多个对象的行为或责任。通知(Advice)是切面在...

    Spring-AOP-JDK动态代理

    5. **配置代理**:Spring会根据目标对象是否实现了接口来决定使用JDK动态代理还是CGLIB代理。如果目标对象实现了接口,Spring会选择JDK动态代理。动态代理类会继承自`java.lang.reflect.Proxy`,并实现目标对象的...

    spring-aop源码解读

    Spring支持两种类型的代理:JDK动态代理和CGLIB代理。JDK代理用于实现接口的对象,而CGLIB代理则用于不实现接口的类。ProxyFactoryBean是Spring AOP用于创建代理对象的主要工具,它实现了BeanFactoryAware、...

    AOP之JDK动态代理和CGLib动态代理

    Spring框架是AOP实现的一个典范,它提供了两种主要的动态代理方式:JDK动态代理和CGLib动态代理。 **JDK动态代理**: JDK动态代理基于Java的反射API实现,适用于接口代理。当目标对象实现了至少一个接口时,Spring...

    spring-aop

    2. **org.springframework.aop.framework**:这个包包含了AOP的代理实现,包括JDK动态代理和CGLIB代理。JDK代理用于实现接口的类,而CGLIB代理则用于没有实现接口但需要进行AOP处理的类。Spring会根据目标对象是否...

Global site tag (gtag.js) - Google Analytics