• 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. }

     
  • 相关阅读:
    spring cloud/spring boot同时支持http和https访问
    解决to the cache because there was insufficient free space available after evict
    国外天气api 国际天气预报今天、未来3天、未来7天的天气预报信息接口
    java 访问get接口请求外部的json数据
    IDEA创建基于Maven的SpringBoot项目-多模块
    PostgreSQL提取每个ID的最后一行(Postgresql extract last row for each id)
    Vue项目引入百度地图
    Vue 引入天地图 & 地图类型切换
    js在新窗口打开链接
    mysql使用小数注意
  • 原文地址:https://www.cnblogs.com/a892647300/p/2656901.html
Copyright © 2020-2023  润新知