你的位置:首页 > 软件开发 > Java > 理解三种代理模式

理解三种代理模式

发布时间:2017-10-23 23:00:23
一、代理模式  代理,顾名思义可以简单理解为代为管理,代理模式就是为其他对象提供额外服务,控制访问(前置处理),或做善后处理(后置处理)。有了代理之后,可以在原来功能的基础上由代理完成另外一部分事情。  常见的代理模式有:静态代理:这种代理模式需要代理对象和目标对象实现相同的接口 ...

理解三种代理模式

一、代理模式

  代理,顾名思义可以简单理解为代为管理,代理模式就是为其他对象提供额外服务,控制访问(前置处理),或做善后处理(后置处理)。有了代理之后,可以在原来功能的基础上由代理完成另外一部分事情。

  常见的代理模式有:

      • 静态代理:这种代理模式需要代理对象和目标对象实现相同的接口。可以在不修改目标对象的基础上扩展功能。
        • 缺点:静态代理由于需要和目标对象实现相同的接口,当代理对象变多的时候代理类就会跟着增加,而且一旦更改了接口,那么目标对象和代理对象都要同时做出调整,不方便管理。
      • 动态代理:代理对象不需要实现目标对象接口,通过JAVA的API动态生成目标对象的代理对象。Proxy.newProxyInstance(。。。),其中有三个参数:
        • ClassLoader loader:目标对象的类加载器
        • Class<?>[] interfaces:目标对象的接口类型
        • InvocationHandler h:事件处理函数,实现对目标对象的操作。
      • CGLIB动态代理:也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展。
        • JDK的动态代理有一个限制,就是使用动态代理的对象必须实现一个或多个接口,如果想代理没有实现接口的类,就可以使用Cglib实现.
        • Cglib是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口.它广泛的被许多AOP的框架使用,例如Spring AOP和synaop,为他们提供方法的interception(拦截)
        • Cglib包的底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类.不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.

二、静态代理(需要接口)

  静态代理需要目标对象和代理对象实现相同的接口:

  UserDaoInterface接口类:

1 public interface UserDaoInterface {2  public void save();3 }

  目标对象:

1 public class UserDao implements UserDaoInterface {2  public void save() {3   System.out.println("保存用户信息中。。。。");4  }5 }

  代理对象:

 1 /** 2  * 代理对象,和目标对象实现相同接口 3 */ 4 public class UserDaoProxy implements UserDaoInterface { 5  private UserDaoInterface userDao; 6  7  public UserDaoProxy(UserDaoInterface userDao) { 8   this.userDao = userDao; 9  }10 11  public void save() {12   System.out.println("开始保存");13   userDao.save();14   System.out.println("保存成功");15  }16 }

  测试类:

1 public class Test {2  @org.junit.jupiter.api.Test3  public void testDemo(){4   System.out.println("静态代理");5   //获取对象6   UserDaoInterface userDao = new UserDaoProxy(new UserDao());7   userDao.save();8  }9 }

  实现结果:

理解三种代理模式

  如果要增加接口的方法,目标对象和代理对象类都需要修改。

三、动态代理(需要接口)

  动态代理,代理对象无需刻意实现目标对象接口。

  接口类

1 public interface UserDaoInterface {2  public void save();3 }

  目标类

1 public class UserDao implements UserDaoInterface {2  public void save() {3   System.out.println("保存用户信息中。。。。");4  }5 }

 

  代理类(动态代理,代理类没有实现和目标对象一样的接口 而是通过javaAPI在内存中为我们动态创建了一个代理对象)

 1 /** 2  * 代理工厂类 3 */ 4 public class ProxyFactory { 5  private Object obj; 6  7  public ProxyFactory(Object obj) { 8   this.obj = obj; 9  }10 11  public Object getInstance(){12   return Proxy.newProxyInstance(obj.getClass().getClassLoader(),13    obj.getClass().getInterfaces(),14    new InvocationHandler() {15     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {16      System.out.println("开始保存");17      Object returnObject = method.invoke(obj,args);18      System.out.println("保存成功");19      return returnObject;20     }21    });22  }23 }

 

  测试类:

 1 public class Test { 2  @org.junit.jupiter.api.Test 3  public void testDemo(){ 4   System.out.println("动态代理"); 5   UserDaoInterface target = new UserDao(); 6   UserDaoInterface proxy =(UserDaoInterface) new ProxyFactory(target).getInstance(); 7   proxy.save(); 8   System.out.println("原生对象:"+target.getClass()); 9   System.out.println("代理对象:"+proxy.getClass());10  }11 }

  运行结果:

理解三种代理模式

从结果中我们可以看出返回的是一个javaAPI的代理对象。

四、CGLIB代理(无需接口)

  CGLIB代理不需要目标对象有实现接口,它通过构建目标对象的子类对目标功能进行扩展

  目标对象类:

1 public class UserDao{2  public void save(){3   System.out.println("保存用户信息");4  }5 }

 

   代理对象类:

 1 public class CglibProxy implements MethodInterceptor { 2  3  private Object target; 4  5  public CglibProxy(Object target) { 6   this.target = target; 7  } 8  9  //给目标对象创建代理对象10  public Object getProxyInstance(){11   /**12    * 1.工具类,允许为非接口类型创建一个Java代理。Enhancer动态创建了给定类型的子类但是拦截了所有的方法。13    * 和Proxy不一样的是,不管是接口还是类他都能正常工作14   */15   Enhancer en = new Enhancer();16   /**17    * 2.设置父类18   */19   en.setSuperclass(target.getClass());20   /**21    * 3.设置回掉函数(因为MethodInterceptor继承了Callback类,默认执行intercept方法)22   */23   en.setCallback(this);24   /**25    * 4.创建子类26   */27   return en.create();28  }29 30  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {31   System.out.println("开始保存");32   Object returnObject = method.invoke(target,objects);33   System.out.println("保存结束");34   return returnObject;35  }36 }

    测 试类:

1 public class Test {2  @org.junit.jupiter.api.Test3  public void testDemo(){4   System.out.println("cglib代理");5   UserDao userDao =(UserDao) new CglibProxy(new UserDao()).getProxyInstance();6   userDao.save();7  }8 }

 

  运行结果:

   理解三种代理模式

 

 

 

 

原标题:理解三种代理模式

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录