转载 cglib代理和java代理
Java动态代理之JDK实现和CGlib实现(简单易懂)
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6542259.html
一:代理模式(静态代理)
代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。
静态代理由 业务实现类、业务代理类 两部分组成。业务实现类 负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理,主要是在方法中首先进行预处理动作,然后调用业务实现类的方法,还可以规定调用后的操作。我们在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被代理类处理过的业务方法。
静态代理的实现:
1:首先定义一个接口,说明业务逻辑。
package net.battier.dao; /** * 定义一个账户接口 * @author Administrator*/ public interface Count { // 查询账户public void queryCount(); // 修改账户 public void updateCount(); }
2:然后,定义业务实现类,实现业务逻辑接口
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("修改账户..."); } }
3:定义业务代理类:通过组合,在代理类中创建一个业务实现类对象来调用具体的业务方法;通过实现业务逻辑接口,来统一业务方法;在代理类中实现业务逻辑接口中的方法时,进行预处理操作、通过业务实现类对象调用真正的业务方法、进行调用后操作的定义。
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("修改账户之后——————————"); } }
4:在使用时,首先创建业务实现类对象,然后把业务实现类对象作构造参数创建一个代理类对象,最后通过代理类对象进行业务方法的调用。
public static void main(String[] args) { CountImpl countImpl = new CountImpl(); CountProxy countProxy = new CountProxy(countImpl); countProxy.updateCount(); countProxy.queryCount(); }
静态代理的缺点很明显:一个代理类只能对一个业务接口的实现类进行包装,如果有多个业务接口的话就要定义很多实现类和代理类才行。而且,如果代理类对业务方法的预处理、调用后操作都是一样的(比如:调用前输出提示、调用后自动关闭连接),则多个代理类就会有很多重复代码。这时我们可以定义这样一个代理类,它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用。——那就是动态代理。
二:动态代理的第一种实现——JDK动态代理
JDK动态代理所用到的代理类在程序调用到代理类对象时才由JVM真正创建,JVM根据传进来的 业务实现类对象 以及 方法名 ,动态地创建了一个代理类的class文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。我们需要做的,只需指定代理类的预处理、调用后操作即可。
1:首先,定义业务逻辑接口
public interface BookFacade { public void addBook(); }
2:然后,实现业务逻辑接口创建业务实现类
public class BookFacadeImpl implements BookFacade { @Override public void addBook() { System.out.println("增加图书方法。。。"); } }
3:最后,实现 调用管理接口InvocationHandler 创建动态代理类
public class BookFacadeProxy implements InvocationHandler { private Object target;//这其实业务实现类对象,用来调用具体的业务方法 /** * 绑定业务对象并返回一个代理类 */ public Object bind(Object target) { this.target = target; //接收业务实现类对象参数//通过反射机制,创建一个代理类对象实例并返回。用户进行方法调用时使用//创建代理对象时,需要传递该业务类的类加载器(用来获取业务实现类的元数据,在包装方法是调用真正的业务方法)、接口、handler实现类return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } /** * 包装调用方法:进行预处理、调用后处理 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result=null; System.out.println("预处理操作——————"); //调用真正的业务方法 result=method.invoke(target, args); System.out.println("调用后处理——————"); return result; } }
4:在使用时,首先创建一个业务实现类对象和一个代理类对象,然后定义接口引用(这里使用向上转型)并用代理对象.bind(业务实现类对象)的返回值进行赋值。最后通过接口引用调用业务方法即可。(接口引用真正指向的是一个绑定了业务类的代理类对象,所以通过接口方法名调用的是被代理的方法们)
public static void main(String[] args) { BookFacadeImpl bookFacadeImpl=new BookFacadeImpl();BookFacadeProxy proxy = new BookFacadeProxy(); BookFacade bookfacade = (BookFacade) proxy.bind(bookFacadeImpl); bookfacade.addBook(); }
JDK动态代理的代理对象在创建时,需要使用业务实现类所实现的接口作为参数(因为在后面代理方法时需要根据接口内的方法名进行调用)。如果业务实现类是没有实现接口而是直接定义业务方法的话,就无法使用JDK动态代理了。并且,如果业务实现类中新增了接口中没有的方法,这些方法是无法被代理的(因为无法被调用)。
三:动态代理的第二种实现——CGlib
cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。
1:首先定义业务类,无需实现接口(当然,实现接口也可以,不影响的)
public class BookFacadeImpl1 { public void addBook() { System.out.println("新增图书..."); } }
2:实现 MethodInterceptor方法代理接口,创建代理类
public class BookFacadeCglib implements MethodInterceptor { private Object target;//业务类对象,供代理方法中进行真正的业务方法调用//相当于JDK动态代理中的绑定public Object getInstance(Object target) { this.target = target; //给业务对象赋值Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦 enhancer.setCallback(this); // 创建动态代理类对象并返回 return enhancer.create(); } // 实现回调方法 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; }
3:创建业务类和代理类对象,然后通过 代理类对象.getInstance(业务类对象) 返回一个动态代理类对象(它是业务类的子类,可以用业务类引用指向它)。最后通过动态代理类对象进行方法调用。
public static void main(String[] args) { BookFacadeImpl1 bookFacade=new BookFacadeImpl1();BookFacadeCglib cglib=new BookFacadeCglib(); BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(bookFacade); bookCglib.addBook(); }
四:比较
静态代理是通过在代码中显式定义一个业务实现类一个代理,在代理类中对同名的业务方法进行包装,用户通过代理类调用被包装过的业务方法;
JDK动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;
CGlib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;
转载于:https://www.cnblogs.com/zyzcj/p/7268957.html
转载 cglib代理和java代理相关推荐
- 八 web爬虫讲解2—urllib库爬虫—ip代理—用户代理和ip代理结合应用
使用IP代理 ProxyHandler()格式化IP,第一个参数,请求目标可能是http或者https,对应设置 build_opener()初始化IP install_opener()将代理IP设置 ...
- ip模拟工具_HTTP代理和IP代理有什么区别
在我们互联网工作者当中,HTTP代理和IP代理相信都不陌生.因为在大家工作的时候,一些特定的领域或者功能需要通过代理软件来完成.虽然这个软件不是一定要使用,可是一旦不用不仅会让工作效率变低,爬虫工作者 ...
- Socks5代理和IP代理
Socks5代理和IP代理是常用的网络代理服务,它们为用户提供了匿名访问和保护隐私的功能.在本文中,我们将介绍这两种代理的基本概念和工作原理,并展示如何编写一个简单的代理服务器. 一.什么是Socks ...
- 详细的HTTP代理和SOCKS代理
代理,也称为网络代理,是一种特殊的网络服务,它允许网络终端(通常是客户端)通过此服务与另一个网络终端(通常是服务器)进行间接连接.详细的HTTP代理和SOCKS代理 代理的主要目的是更改IP地址.市场 ...
- socks5代理和HTTP代理有什么区别呢?
首先,让我们来了解一下什么是代理.代理是一种在网络中用于隐藏客户端真实IP地址的技术,它允许客户端通过中间代理服务器进行网络请求和响应.而代理服务器则会将客户端请求转发给目标服务器,接收到响应后再转发 ...
- HTTP代理和HTTPS代理的区别
随着代理服务器的广泛使用,大家多少对这一工具有一些了解,今天我们就来看看HTTP代理和HTTPS代理的工作流程有哪些不同? HTTP协议即超文本传输协议,它的全称为Hyper Text Transfe ...
- http代理和SOCK5代理,我们在使用中选择哪一个,是不是HTTP是明码,不够安全?
我们在选择代理IP时,会发现代理IP有各种各样的类型,什么长效代理IP.短效代理IP.普匿代理IP.高匿代理IP.动态代理IP等等,当然还有今天的主角,http代理IP和Socks代理IP.这其实是更 ...
- socks5代理和http代理流程
代理分类 一.正向代理(forward proxy) 一般所说的代理就是正向代理,客户端使用正向代理时需要知道代理的IP和端口,并发送服务代理格式的请求.代理解析客户端的请求,获取服务器地址后建立连接 ...
- spring 如何决定使用jdk动态代理和cglib(转)
Spring1.2: 将事务代理工厂[TransactionProxyFactoryBean] 或 自动代理拦截器[BeanNameAutoProxyCreator] 的 proxyTargetCla ...
最新文章
- Linux笔记:使用Vim编辑器
- HDLBits 系列(36)Arbitration circuit implemented by FSM
- python【蓝桥杯vip练习题库】ADV-186排列式
- python2.7安装pip_RobotFramework安装过程遇到的问题(电脑同时安装python2和3)
- HTML页面打印功能js代码,JavaScript_js实现页面打印功能实例代码(附去页眉页脚功能代码),复制代码 代码如下: html - phpStudy...
- 将cmd添加到鼠标右键,并且在任意目录下可以打开
- 图像语义分割(10)-DeepLabV3+: 用于图像语义分割的带有空洞可分离卷积的编解码结构
- 获得学士学位的机器学习工程工作
- 关于联想键盘,如何去除fn 键 联想官方解决方法
- Premiere CC2019软件下载和安装教程
- 【2021】【论文笔记】太赫兹量子阱光电探测器——
- 第三方支付接口现号,第三方支付接口对接,第三方支付接口申请
- 海康威视摄像头的多通道rtsp地址格式
- 压缩视图状态之ajax(atlas)修正版
- 解决mac突然连不上wifi了(wifi出现灰色小感叹号!)
- 中兴算法大赛深度学习模型优化加速解决方案总结
- 全球各国主要电商平台
- Linux中常见的指令(三):几个查看文件内容的指令,ctrl+c的理解
- python对淘宝运营有帮助吗_优秀的淘宝运营需要具备哪些能力
- 亲测绝对有用,,电脑不显示可连接WiFi列表,无法连接WiFi的解决办法。