动效网站建设,wordpress 不同菜单,网站一个页面多少钱,网站刷收益是怎么做的转载自 动态代理proxy与CGLib的区别昨天被人问及动态代理与CGlib的区别#xff0c;赶紧回顾一下#xff1a;
什么是代理#xff1f;静态代理与动态代理静态代理实例JDK动态代理实例CGLib 简介CGLib 与JDK动态代理的区别代理模式是Java中常见的一种模式#xff0c;英文名字叫…转载自 动态代理proxy与CGLib的区别昨天被人问及动态代理与CGlib的区别赶紧回顾一下
什么是代理静态代理与动态代理静态代理实例JDK动态代理实例CGLib 简介CGLib 与JDK动态代理的区别代理模式是Java中常见的一种模式英文名字叫走Proxy或者Surrogate代理的本意是一个人代表另一个人或者一个机构代表另一个机构采取行动因而代理和现实生活中的中介有很大的类似你买房子、卖房子可以自己去操作但是需要了解和买卖房产无关的细节如契税等而找一个中介则不用关心这些与买卖房产无直接关系的中间细节只关心业务本身。因而我们可以把代理模式的适用总结为代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类以及事后处理消息等代理模式的用途可以分为如下几种1远程代理Remote 为远程对象的invoke提供代理典型的例子如RMI或者EJB都会在本地生成一个远程对象的stub。2虚拟代理Virtual如果需要创建一个资源消耗大的对象则可以首先使用一个代理使这个对象在需要时才真正创建。3Copy-On-Write 代理把复制延迟到客户端需要时才采取行动4保护Protect5Cache代理2.静态代理与动态代理
代理分为静态代理和动态代理按照代理创建的时期可以分为动态代理和静态代理静态代理由程序员或者自动生成工具生成代理类然后进行代理类的编译和运行。在代理类、委托类运行之前代理类已经以.class的格式存在。动态代理在程序运行时由反射机制动态创建而成。3.静态代理实例静态代理实例首先需要一个接口
[java] view plaincopypackage net.battier.dao; /** * 定义一个账户接口 * * author Administrator * */ public interface Count { // 查看账户方法 public void queryCount(); // 修改账户方法 public void updateCount(); } 然后是委托类也就是接口的真正实现类内涵主要的业务逻辑
[java] view plaincopypackage net.battier.dao.impl; import net.battier.dao.Count; /** * 委托类(包含业务逻辑) * * author Administrator * */ public class CountImpl implements Count { Override public void queryCount() { System.out.println(查看账户方法...); } Override public void updateCount() { System.out.println(修改账户方法...); } } 最后是代理类
[java] view plaincopyCountProxy.java package net.battier.dao.impl; import net.battier.dao.Count; /** * 这是一个代理类增强CountImpl实现类 * * author Administrator * */ public class CountProxy implements Count { private CountImpl countImpl; /** * 覆盖默认构造器 * * param countImpl */ public CountProxy(CountImpl countImpl) { this.countImpl countImpl; } Override public void queryCount() { System.out.println(事务处理之前); // 调用委托类的方法; countImpl.queryCount(); System.out.println(事务处理之后); } Override public void updateCount() { System.out.println(事务处理之前); // 调用委托类的方法; countImpl.updateCount(); System.out.println(事务处理之后); } } 运行
[java] view plaincopypackage com.mahoutchina.pattern.proxy; public class CountTest { /** * param args */ public static void main(String[] args) { CountImpl countImpl new CountImpl(); CountProxy countProxy new CountProxy(countImpl); countProxy.updateCount(); countProxy.queryCount(); } } 从静态代理中可以看出1.接口代理类需要实现一个接口这个接口和委托类的接口是一样的这样proxy才能和委托类行为表现一致2. 方法Method:由于接口限制proxy类中也要有interface中的各个方法这就造成了代码重复4.JDK动态代理实例 动态代理类克服了proxy需要继承专一的interface接口并且要实现相应的method的缺陷。从JDK 1.3以来Java 语言通过java.lang.reflex库提供的三个类直接支持代理java.lang.reflect.Proxy,java.lang.reflect.InvocationHandler 和Method.Proxy类在运行时动态创建代理对象这也是dynamic proxy的由来下面是类图其中最重要的是newProxyInstance,这个方法中指明了将要代理的类的加载器业务类接口以及代理类要执行动作的调用处理器InvokeHandler)public static Object newProxyInstance(ClassLoader loader, Class?[] interfaces, InvocationHandler h) throws IllegalArgumentException 参数说明 ClassLoader loader类加载器 Class?[] interfaces得到全部的接口 InvocationHandler h得到InvocationHandler接口的子类实例
Ps:类加载器 在Proxy类中的newProxyInstance方法中需要一个ClassLoader类的实例ClassLoader实际上对应的是类加载器在Java中主要有一下三种类加载器; Booststrap ClassLoader此加载器采用C编写一般开发中是看不到的 Extendsion ClassLoader用来进行扩展类的加载一般对应的是jre\lib\ext目录中的类; AppClassLoader(默认)加载classpath指定的类是最常使用的是一种加载器。 当系统有了一个代理对象之后对原方法的调用会首先被分派到一个调用处理器Invocation Handler).InvocationHandler 接口如下图所示代码接口
[java] view plaincopypackage com.mahoutchina.pattern.proxy.dynamicproxy; public interface BookFacade { public void addBook(); public void deleteBook(); } 实际业务类
[java] view plaincopypackage com.mahoutchina.pattern.proxy.dynamicproxy; public class BookFacadeImpl implements BookFacade { Override public void addBook() { System.out.println(add book logic is running。。。); } Override public void deleteBook() { System.out.println(delete book logic is running。。。); } } 动态代理类
[java] view plaincopypackage com.mahoutchina.pattern.proxy.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class BookFacadeProxy implements InvocationHandler { private Object target; /** * * param target * return */ public Object bind(Object target) { this.target target; // 取得代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object resultnull; System.out.println(Proxy start...); System.out.println(method name:method.getName()); resultmethod.invoke(target, args); System.out.println(Proxy end...); return result; } } 测试类
[java] view plaincopypackage com.mahoutchina.pattern.proxy.dynamicproxy; ublic class TestProxy { /** * param args */ public static void main(String[] args) { BookFacadeProxy proxy new BookFacadeProxy(); BookFacade bookProxy (BookFacade) proxy.bind(new BookFacadeImpl()); bookProxy.addBook(); bookProxy.deleteBook(); } 对于JDK 的Proxy,有以下几点1Interface对于JDK proxy业务类是需要一个Interface的这也是一个缺陷2ProxyProxy 类是动态产生的这个类在调用Proxy.newProxyInstance(targetCls.getClassLoader, targetCls.getInterface,InvocationHander)之后会产生一个Proxy类的实例。实际上这个Proxy类也是存在的不仅仅是类的实例。这个Proxy类可以保存到硬盘上。3 Method:对于业务委托类的每个方法现在Proxy类里面都不用静态显示出来4 InvocationHandler: 这个类在业务委托类执行时会先调用invoke方法。invoke方法再执行相应的代理操作可以实现对业务方法的再包装5 CGLib 简介JDK的动态代理机制只能代理实现了接口的类而不能实现接口的类就不能实现JDK的动态代理cglib是针对类来实现代理的他的原理是对指定的目标类生成一个子类并覆盖其中方法实现增强但因为采用的是继承所以不能对final修饰的类进行代理。 示例 业务类
[java] view plaincopypackage net.battier.dao; public interface BookFacade { public void addBook(); } [java] view plaincopypackage net.battier.dao.impl; /** * 这个是没有实现接口的实现类 * * author student * */ public class BookFacadeImpl1 { public void addBook() { System.out.println(增加图书的普通方法...); } } 代理
[java] view plaincopypackage net.battier.proxy; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /** * 使用cglib动态代理 * * author student * */ public class BookFacadeCglib implements MethodInterceptor { private Object target; /** * 创建代理对象 * * param target * return */ public Object getInstance(Object target) { this.target target; Enhancer enhancer new Enhancer(); enhancer.setSuperclass(this.target.getClass()); // 回调方法 enhancer.setCallback(this); // 创建代理对象 return enhancer.create(); } Override // 回调方法 public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println(事物开始); proxy.invokeSuper(obj, args); System.out.println(事物结束); return null; } } 测试
[java] view plaincopypackage net.battier.test; import net.battier.dao.impl.BookFacadeImpl1; import net.battier.proxy.BookFacadeCglib; public class TestCglib { public static void main(String[] args) { BookFacadeCglib cglibnew BookFacadeCglib(); BookFacadeImpl1 bookCglib(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1()); bookCglib.addBook(); } }