• 自己写的一个 CGBLIB 动态代理【原创】


    CGLIB代理类,用CGLIB来实现一个代理类。大致原理描述如下:

    1、使用Enhancer类来生成一个继续于被代理类的子类,此子类会重写被代理类(父类)中所有的非final的public方法;

    2、当调用代理类的某个方法时实际上通过一个MethodInterceptor委托来间接调用的;

    3、MethodInterceptor的intercept方法会对被代理类的方法进行增强(增强的逻辑是通过Interceptor接口来实现的)并调用被代理类(super class)的相关方法。

    调用过程如下图:

    CglibProxy类实现核心代理逻辑,并提供一个Interceptor接口供客户端来实现增强逻辑。

    package proxy;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import lombok.AccessLevel;
    import lombok.RequiredArgsConstructor;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    /**
     * @author xfyou
     */
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    public class CglibProxy<T> {
    
      private final Class<T> targetClass;
      private final MethodInterceptor methodInterceptor;
    
      public static <T> CglibProxy<T> newInstance(Class<T> targetClass, Interceptor interceptor) {
        return new CglibProxy<>(targetClass, new MethodInterceptor() {
          @Override
          public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            interceptor.before(obj);
            Object invokeResult;
            try {
              invokeResult = proxy.invokeSuper(obj, args);
            } catch (Throwable e) {
              interceptor.exception(obj, e);
              throw new InvocationTargetException(e);
            }
            interceptor.after(obj);
            return invokeResult;
          }
        });
      }
    
      @SuppressWarnings("unchecked")
      public T createNewObj() {
        return (T) createNewEnhancer().create();
      }
    
      private Enhancer createNewEnhancer() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetClass);
        enhancer.setCallback(methodInterceptor);
        return enhancer;
      }
    
      public interface Interceptor {
    
        /**
         * Do something before invoke the super class method
         *
         * @param obj Instances of proxied objects
         */
        void before(Object obj);
    
        /**
         * Do something after invoked the super class method
         *
         * @param obj Instances of proxied objects
         */
        void after(Object obj);
    
        /**
         * Do something when exception occurred when invoke the super class method
         *
         * @param obj Instances of proxied objects
         * @param e Exception
         */
        void exception(Object obj, Throwable e);
    
      }
    
    }

     WorkProxy类用来对Work类进行代理,生成的是一个单例的代理类。

    package proxy;
    
    import proxy.CglibProxy.Interceptor;
    
    /**
     * @author xfyou
     * @date 2019/10/15
     */
    public class WorkProxy {
    
      private static Work proxyObject;
    
      private static Interceptor interceptor = new Interceptor() {
    
        @Override
        public void before(Object obj) {
          System.out.println("before");
        }
    
        @Override
        public void after(Object obj) {
          System.out.println("after");
        }
    
        @Override
        public void exception(Object obj, Throwable e) {
          System.out.println("exception");
        }
    
      };
    
      static {
        proxyObject = CglibProxy.newInstance(Work.class, interceptor).createNewObj();
      }
    
      public static Work get() {
        return proxyObject;
      }
    
    }

    被代理的Work类如下:

    package proxy;
    
    /**
     * Work
     */
    public class Work {
    
        public void doWork() {
            System.out.println("Do work");
        }
    
    }

    测试代码:

    package proxy;
    
    /**
     * @author xfyou
     * @date 2019/10/15
     */
    public class Test {
    
      public static void main(String[] args) {
        WorkProxy.get().doWork();
      }
    
    }
  • 相关阅读:
    40岁后学习编程是否太晚了?7点技巧让学习变得轻松有趣
    Java 8五大主要功能为开发者提供了哪些便利?
    如何创建Vim Dotfile?
    程序员:我们为什么爱上直播编程?
    10个最好用的HTML/CSS 工具、插件和资料库
    如何选择PHP框架?
    编程语言五花八门,哪种可以让程序员赚到更多钱?
    安卓项目中使用JSON引发的一个小错误 Multiple dex files define Lorg/apache/commons/collections/Buffer
    (转)获取当前应用的版本号和当前android系统的版本号
    Android访问网络,使用HttpURLConnection还是HttpClient?
  • 原文地址:https://www.cnblogs.com/frankyou/p/11679266.html
Copyright © 2020-2023  润新知