zoukankan      html  css  js  c++  java
  • JDK动态代理和CGLIB动态代理

    动态代理模式:

    动态代理的意义在于生成一个代理对象,来代理真实的对象,在真实对象访问之前或者之后加入对应的逻辑,或者控制是否使用真实的对象。

    为了实现代理的功能,代理的两个步骤为:

    l  代理对象和真实对象之间建立代理关系

    l  实现代理对象的逻辑方法

    在java中有多种动态代理技术,其中常用的动态代理技术有两种:一种是JDK动态代理技术(jdk自带的功能),另一种是CGLIB(第三方提供)

    一. JDK动态代理

    Java.lang.reflect.*提供的动态代理方式,其必须定义一个接口才能产生代理对象。

    1. 定义接口
      package proxy;
      
      public interface Helloworld {
          public void sayHelloworld();
      }

      2.接口实现类

      package proxy;
      
      public class HelloworldImpl implements Helloworld{
      
          @Override
          public void sayHelloworld() {
              // TODO Auto-generated method stub
              System.out.println("Hello world");
          }
          
      
      }

      3.建立JDK动态代理,根据刚开始我们说的两个步骤分别实现bind和invoke方法

      package proxy;
      import java.lang.reflect.*;
      
      public class JdkProxyExample implements InvocationHandler{
          public Object target = null;
          
      //    建立真实对象和代理对象之间的代理关系,并返回代理关系
          public Object bind(Object target) {
              this.target = target;
              return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
          }
      
      //    @Override
      //    代理方法逻辑
      //    @param proxy 代理对象
      //    @param method 当前调度方法
      //    @param args 当前方法参数
      //    @return 代理结果返回
      //    @throes Throwable 异常
          
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              
              System.out.println("进入代理逻辑方法");
              System.out.println("在调度真实对象之前的调度");
              Object obj = method.invoke(target, args);//相当于调用了sayHelloworld方法
              System.out.println("在调用真实对象之后的服务");
              return obj;
          }
          
      
      }

      步骤一:建立代理对象与真实对象之间的代理关系(bind方法)方法里首先使用了类属性保存了真实对象 在通过如下代码生成代理对象

      return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

      NewProxyInstance包含三个参数:

      l  Target.getClass().getClassLoader():真实对象的类加载器,

      l  Target.getClass().getInterfaces():把生成的代理对象挂在Helloworld的接口上

      l  This:定义实现方法咯及的代理类,this表示当前对象,它必须是实现InvocationHandler接口的invoke方法,是动态代理逻辑方法的现实方法。

      步骤二:实现代理逻辑方法:

      Invoke方法的参数含义:

      Proxy:代理对象,即bind方法生成的对象

      Method:当前调用的方法

      Args:调度方法的参数

      我们使用了代理对象的方法后,它就会进入invoke方法里面

       Object obj = method.invoke(target, args);//相当于调用了真实对象的sayHelloworld方法

      这是通过反射实现对真实方法的调用。

      测试JDK动态代理代码:

      package proxy;
      
      public class TestJdkProxy {
          public static void main(String[] args) {
          JdkProxyExample jdk = new JdkProxyExample();
          Helloworld proxy = (Helloworld)jdk.bind(new HelloworldImpl());
          proxy.sayHelloworld();
          }
      
      }

      结果:

    2. 二. CGLIB动态代理:

      CGLIB动态代理的优势在于不需要提供接口,只需要一个非抽象类就能实现动态代理。

      非抽象类代码如下:

      package cglib;
      
      public class Helloworld {
          public void sayHelloworld(String name) {
              System.out.println("Hello,"+name);
          }
      
      }
      
      

      Cglib动态代理:

      package cglib;
      
      import java.lang.reflect.Method;
      
      import net.sf.cglib.proxy.Enhancer;
      import net.sf.cglib.proxy.MethodInterceptor;
      import net.sf.cglib.proxy.MethodProxy;
      
      public class CglibProxyExample implements MethodInterceptor{
          
          public Object getProxy(Class cls) {
              Enhancer enhancer = new Enhancer();
              enhancer.setSuperclass(cls);
              enhancer.setCallback(this);
              return enhancer.create();
              
          }
      
          @Override
          public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
              System.out.println("调用真实对象前");
              Object result = methodProxy.invokeSuper(proxy,args);
              System.out.println("调用真实对象后");
              return result;
              
          }
      
      }

      这里用了CGLIB的加强者Enhancer,通过设置超类的方法建立代理关系,通过setCallback方法设置代理类,this指当前对象,实现MethodInterceptor的方法(intercept)

      方法参数含义:

      Proxy:代理对象

      Method:方法

      Args:方法参数

      MethodProxy:方法代理

      Return  返回代理逻辑

      测试类:

      package cglib;
      
      public class TestCglibProxy {
          public static void main(String[] args) {
              CglibProxyExample Cglib = new CglibProxyExample();
              Helloworld proxy = (Helloworld)Cglib.getProxy(Helloworld.class);
              proxy.sayHelloworld("fanl");
          }
      
      }

  • 相关阅读:
    JS保留两位小数
    xml,json,html格式化工具
    SQL查询递归
    javascript验证价格输入
    类库说明文档生成器
    转换数据库时间字段格式函数
    mysql python 汉字乱码的解决方案
    Python list 按元素属性排序, key 的用法
    原以为会不同的
    libsvm 文本分类(分两类)(实验结果)直接调用Libsvm工具
  • 原文地址:https://www.cnblogs.com/Mrfanl/p/9492209.html
Copyright © 2011-2022 走看看