zoukankan      html  css  js  c++  java
  • 设计模式(一) 动态代理初尝试

    • 摘要
        之前老是听说动态代理,一直没有机会好好看过,现在就把动态代理的实现逻辑和用处整理一下。
      首先提两个概念,委托类和代理类。委托类就是实际业务逻辑的处理者,代理类是处于请求发起者与委托类之间的角色,所有对委托类的请求都会经过代理类。
      就是委托类将请求处理委托给代理类,代理类可以起到方法拦截、功能增强的作用。
      实现动态代理的方式有很多,现在主流的主要jdk和cglib这两个。下面就用示例代码说明下动态代理的过程,以及用动态代理实现拦截器。
    • 用JDK实现动态代理
        jdk实现动态代理的包是java.lang.reflect.*,jdk实现动态代理有限制,委托类必须要实现接口,所以先要创建一个接口
      public interface MyInterface {
      
          //jdk
          public void tes1();
      
          //cglib
          public void test2(String val);
      
      }


      创建接口实现类

      public class MyTarget implements MyInterface {
      
          //jdk
          @Override
          public void tes1() {
              System.out.println("委托类业务处理!");
          }
      
          //cglib
          @Override
          public void test2(String val) {
              System.out.println("业务处理结果:"+val);
          }
      }


      动态代理逻辑代码

      package proxy;
      
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      
      public class MyProxyTest implements InvocationHandler {  //继承InvocationHandler,拦截方法
      
          private Object target=null;
      
          //构造函数
          public MyProxyTest(Object target){
              this.target = target ;
          }
      
          //获取代理类的方法
          public static Object getProxy(Object target){
              //通过proxy创建代理类,需要三个参数,委托类的类加载器、委托类实现的接口、代理类
              /**
               * 这是jdk的动态代理模式,必须要有接口
               * proxy会把代理类挂载到所有接口下面
               * 如果委托类没有实现任何接口会有问题,改用CGLIB的enhancer增强类做动态代理
               */
              return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                      target.getClass().getInterfaces(),new MyProxyTest(target));
          }
      
          //拦截方法
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              System.out.println("进入代理逻辑!");
              System.out.println("代理类处理逻辑!");
              Object result=null;
              result = method.invoke(target,args);
              System.out.println("委托类处理完后的逻辑!");
              return result;
          }
      }

        getProxy方法就是绑定委托类和代理类之间关系的方法,这里绑定的代理类是this当前对象,也就是MyProxyTest 的实例对象,由于实现了InvocationHandler接口,所以在方法调用之前都会
      通过invoke方法,在这里就可以写功能增强的代码。method.invoke(target,args)是通过反射运行委托类的方法。

      测试用例

      public class JunitTest {
          public static void main(String[] args) {
              /**
               * jdk动态代理
               */
              System.out.println("---------jdk动态代理--------");
              //委托类
              MyTarget target = new MyTarget();
              //给委托类绑定代理类
              MyInterface proxy = (MyInterface)MyProxyTest.getProxy(target);
              proxy.tes1();
          }
      }


      运行结果

      ---------jdk动态代理--------
      进入代理逻辑!
      代理类处理逻辑!
      委托类业务处理!
      委托类处理完后的逻辑!

      我们发现进入了代理类的处理逻辑。



    • CGLIB实现动态代理
        CGLIB实现动态代理和JDK大同小异,不过CGLIB是通过创建增强类Enhancer,并且设置Enhancer的委托类和代理类来实现动态代理。CGLIB的委托类不需要实现接口。
      动态代理逻辑
      package proxy;
      
      import org.springframework.cglib.proxy.Enhancer;
      import org.springframework.cglib.proxy.MethodInterceptor;
      import org.springframework.cglib.proxy.MethodProxy;
      
      import java.lang.reflect.Method;
      
      public class MyCgLibProxy implements MethodInterceptor {
      
          public Object getProxy(Class target){
              //创建增强类
              Enhancer enhancer = new Enhancer();
              //设置委托类
              enhancer.setSuperclass(target);
              //设置代理类
              enhancer.setCallback(this);
              return enhancer.create();
          }
      
      
          @Override
          public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
              System.out.println("进入代理逻辑!");
              System.out.println("代理类处理逻辑!");
              Object result=null;
              result = methodProxy.invokeSuper(o,objects);
              System.out.println("委托类处理完后的逻辑!");
              return result;
          }
      }

      这里的getProxy接收的不是委托类的实例对象而是委托类。代理类是this,MyCgLibProxy 的实例对象,由于实现了MethodInterceptor拦截器,所以方法调用都会经过intercept。

      测试用例

      package proxy;
      
      public class JunitTest {
          public static void main(String[] args) {
              /**
               * cglib动态代理
               */
              System.out.println("---------cglib动态代理--------");
              MyCgLibProxy cgLib = new MyCgLibProxy();
              MyInterface cgLibProxy = (MyInterface)cgLib.getProxy(MyTarget.class);
              cgLibProxy.test2("cglib动态代理");
          }
      }

      运行结果

      ---------cglib动态代理--------
      进入代理逻辑!
      代理类处理逻辑!
      业务处理结果:cglib动态代理
      委托类处理完后的逻辑!

      简单的实现动态代理的两种方式就完成了,之后再讲解拦截器和责任链模式

  • 相关阅读:
    NSData和NSString 、 NSFileManager
    通知(Notification) 、 应用间通信(一)
    Dynamic支持CollectionView布局 、 MotionEffects特效 、 BlurImage效果 、 TextKit
    Dynamic Animator 、 CollectionViewLayout
    动画(Animation) 、 高级动画(Core Animation)
    Autoresizing和AutoLayout
    触控(Touch) 、 布局(Layout)
    手势与变形 、 视图与坐标系
    常用的静态变量,包括颜色等
    JSPatch动态修改已上架app的bug,即时修复bug
  • 原文地址:https://www.cnblogs.com/zhouyun-yx/p/10438383.html
Copyright © 2011-2022 走看看