Spring 动态代理

AOP功能强大,但是spring是如何来实现AOP技术的呢? 
SPRING是通过动态代理来实现AOP的,SPRING内部提供了2种实现机制 
1.如果是有接口声明的类进行AOP,spring调用的是java.lang.reflection.Proxy类来做处理 

Java代码  收藏代码
  1. org.springframework.aop.framework.JdkDynamicAopProxy  
  2.     public Object getProxy(ClassLoader classLoader) {  
  3.         if (logger.isDebugEnabled()) {  
  4.             Class targetClass = this.advised.getTargetSource().getTargetClass();  
  5.             logger.debug("Creating JDK dynamic proxy" +  
  6.                     (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));  
  7.         }  
  8.         Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);  
  9.         return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  
  10.     }  
  11.   
  12. org.springframework.aop.framework.ReflectiveMethodInvocation  
  13. public Object proceed() throws Throwable {  
  14.         //  We start with an index of -1 and increment early.  
  15.         if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {  
  16.             return invokeJoinpoint();  
  17.         }  
  18.   
  19.         Object interceptorOrInterceptionAdvice =  
  20.             this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);  
  21.         if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {  
  22.             // Evaluate dynamic method matcher here: static part will already have  
  23.             // been evaluated and found to match.  
  24.             InterceptorAndDynamicMethodMatcher dm =  
  25.                 (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;  
  26.             if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {  
  27.                 return dm.interceptor.invoke(this);  
  28.             }  
  29.             else {  
  30.                 // Dynamic matching failed.  
  31.                 // Skip this interceptor and invoke the next in the chain.  
  32.                 return proceed();  
  33.             }  
  34.         }  
  35.         else {  
  36.             // It's an interceptor, so we just invoke it: The pointcut will have  
  37.             // been evaluated statically before this object was constructed.  
  38.             return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);  
  39.         }  
  40.     }  


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

Java代码  收藏代码
  1. 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.     }  



我们自己也可以来试试 
1.jdk proxy方式 

先来一个接口 
IHelloWorld.java 

Java代码  收藏代码
  1. package kris.aop.test;  
  2.   
  3. public interface IHelloWorld {  
  4.   
  5.     public void print(String name);  
  6.       
  7.     public void write(String sth);  
  8. }  



再来一个实现 

HelloWorld.java 

Java代码  收藏代码
  1. package kris.aop.test;  
  2.   
  3. public class HelloWorld implements IHelloWorld {  
  4.   
  5.     public void print(String name){  
  6.         System.out.println("HelloWorld "+name);  
  7.     }  
  8.   
  9.     public void write(String sth) {  
  10.         System.out.println("write "+sth);  
  11.           
  12.     }  
  13.   
  14. }  


代理类 

DefaultInvocationHandler.java 

Java代码  收藏代码
  1. package kris.aop.test;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5.   
  6. public class DefaultInvocationHandler implements InvocationHandler {  
  7.   
  8.     /** 
  9.      * 替换外部class调用的方法 
  10.      * obj      外部已经已经包装好InvocationHandler的实例 
  11.      * method   外部方法 
  12.      * args     方法参数 
  13.      */  
  14.     public Object invoke(Object obj, Method method, Object[] args)  
  15.             throws Throwable {  
  16.         String s1 []={"kris"};  
  17.         String s2 []={"anyone"};  
  18.         IHelloWorld ihw=new HelloWorld();  
  19.         System.out.println("start!");  
  20.         method.invoke(ihw,args);  
  21.         method.invoke(ihw,s1);  
  22.         Object o=method.invoke(ihw,s2);  
  23.         System.out.println("stop!");  
  24.         return o;  
  25.     }  
  26.   
  27. }  


测试类 
Test.java 

Java代码  收藏代码
  1. package kris.aop.test;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Proxy;  
  5.   
  6. public class Test {  
  7.   
  8.     public static void main(String args []){  
  9.         Class clazz = new HelloWorld().getClass();  
  10.         ClassLoader cl = clazz.getClassLoader();  
  11.         Class classes [] = clazz.getInterfaces();  
  12.         InvocationHandler ih=new DefaultInvocationHandler();  
  13.         //用InvocationHandler给HelloWorld进行AOP包装  
  14.         IHelloWorld ihw=(IHelloWorld) Proxy.newProxyInstance(cl,classes,ih);  
  15.         ihw.print("test");  
  16.         ihw.write("test");  
  17.     }  
  18. }  



2.用CGLIB包实现,首先不要忘了引入那个包 

Java代码  收藏代码
  1. package kris.aop.cglib.test;  
  2.   
  3. public class HelloWorld {  
  4.   
  5.     public void print(String name){  
  6.         System.out.println("HelloWorld "+name);  
  7.     }  
  8.   
  9.     public void write(String sth) {  
  10.         System.out.println("write "+sth);  
  11.           
  12.     }  
  13.     public void print(){  
  14.         System.out.println("HelloWorld");  
  15.     }  
  16.   
  17. }  


代理类(没用内部类,看起来清楚点) 

Java代码  收藏代码
  1. package kris.aop.cglib.test;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. import net.sf.cglib.proxy.MethodInterceptor;  
  6. import net.sf.cglib.proxy.MethodProxy;  
  7.   
  8. public class MethodInterceptorImpl implements MethodInterceptor {  
  9.   
  10.     public Object intercept(Object obj, Method method, Object[] args,  
  11.             MethodProxy proxy) throws Throwable {  
  12.   
  13.         System.out.println(method);  
  14.   
  15.         proxy.invokeSuper(obj, args);  
  16.   
  17.         return null;  
  18.     }  
  19. }  


测试类 
Java代码  收藏代码
  1. package kris.aop.cglib.test;  
  2.   
  3. import net.sf.cglib.proxy.Enhancer;  
  4.   
  5. public class Test {  
  6.   
  7.     public static void main(String[] args) {  
  8.   
  9.         Enhancer enhancer = new Enhancer();  
  10.   
  11.         enhancer.setSuperclass(HelloWorld.class);  
  12.         //设置回调方法实现类  
  13.         enhancer.setCallback(new MethodInterceptorImpl());  
  14.         //实例化已经添加回调实现的HELLOWORLD实例  
  15.         HelloWorld my = (HelloWorld) enhancer.create();  
  16.   
  17.         my.print();  
  18.     }  
  19.   
  20. }

 
posted @ 2012-08-25 20:41  New~one  阅读(397)  评论(0编辑  收藏  举报