- 浏览: 2152321 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (682)
- 软件思想 (7)
- Lucene(修真篇) (17)
- Lucene(仙界篇) (20)
- Lucene(神界篇) (11)
- Solr (48)
- Hadoop (77)
- Spark (38)
- Hbase (26)
- Hive (19)
- Pig (25)
- ELK (64)
- Zookeeper (12)
- JAVA (119)
- Linux (59)
- 多线程 (8)
- Nutch (5)
- JAVA EE (21)
- Oracle (7)
- Python (32)
- Xml (5)
- Gson (1)
- Cygwin (1)
- JavaScript (4)
- MySQL (9)
- Lucene/Solr(转) (5)
- 缓存 (2)
- Github/Git (1)
- 开源爬虫 (1)
- Hadoop运维 (7)
- shell命令 (9)
- 生活感悟 (42)
- shell编程 (23)
- Scala (11)
- MongoDB (3)
- docker (2)
- Nodejs (3)
- Neo4j (5)
- storm (3)
- opencv (1)
最新评论
-
qindongliang1922:
粟谷_sugu 写道不太理解“分词字段存储docvalue是没 ...
浅谈Lucene中的DocValues -
粟谷_sugu:
不太理解“分词字段存储docvalue是没有意义的”,这句话, ...
浅谈Lucene中的DocValues -
yin_bp:
高性能elasticsearch ORM开发库使用文档http ...
为什么说Elasticsearch搜索是近实时的? -
hackWang:
请问博主,有用solr做电商的搜索项目?
Solr中Group和Facet的用法 -
章司nana:
遇到的问题同楼上 为什么会返回null
Lucene4.3开发之第八步之渡劫初期(八)
文章关键词:java代理,jdk动态代理,cglib代理,AOP,切面编程
今天,逛技术博客时,无意间发现了一篇有关动态代理模式的文章,感觉写的不错,自己正好也在巩固下基础知识,虽然实际工作中用代理的模式的不是特别多,那是因为你使用的框架,已经帮你封装好了,所以,你可能感觉不到,但是感觉不到不但表不存在,了解下它的原理和使用场景还是能提高下逼格的。于是散仙总结了下文,还有一个实战小例子,用来帮助理解。下面开始:
一:什么是代理?
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
说白了,代理模式其实就相当于找房子时的中介,你无须找到真实的房东,就可以把租房子这件事给办了,而且因为中介,所以便有了一些额外增强的功能,所以少数中介会提高房价或黑你一下,当然咱们的程序肯定不是跟中介一个德行的。
二:java中代理的种类
(1)静态代理: 只能提供固定的类的代理,局限性比较大
(2)JDK动态代理:只能代理接口,通过反射,提高了灵活性,但性能稍慢
(3)CGLIB代理:Spring AOP的默认实现,可以代理类,无须提供对应接口,通过ASM(asm是Java字节码操控框架,ASM是一套java字节码生成架构,它可以动态生成二进制格式的stub类或其它代理类,或者在类被java虚拟机装入内存之前,动态修改类)字节码增强,速度要快于JDK的默认的动态代理。
三:使用代理的应用场景
这个问题,其实就跟问Spring AOP切面编程的好处,就非常类似了,通过代理模式,我们可以无侵入式的,很方便的实现日志记录功能,方法权限拦截功能,事务控制等功能。
四:实战例子
项目结构:
百度云盘下载: http://pan.baidu.com/s/1eQ0h5YE
1,JDK动态代理,模拟事务控制功能,已经记录方法的耗时功能
Dao接口已经实现类,里面含有测试的方法:
实现类:
JDK动态代理实现:
无接口的cglib代理测试类:
Cglib代理的实现:
测试的代码:
测试JDK动态代理结果:
测试cglib代理结果:
总结:使用代理模式,在一些场景,非常灵活,而且无侵入式的发挥巨大的作用,这就是面向切面编程的核心思想。
最后欢迎大家扫码关注微信公众号:我是攻城师(woshigcs),我们一起学习,进步和交流!(woshigcs)
本公众号的内容是有关搜索和大数据技术和互联网等方面内容的分享,也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!
参考文章:
http://andy136566.iteye.com/blog/967952
http://www.cnblogs.com/coderworld/p/java-reflect.html
http://blog.csdn.net/leon709/article/details/9529307
http://www.cnblogs.com/coderworld/p/java-dynamic-proxy.htm
今天,逛技术博客时,无意间发现了一篇有关动态代理模式的文章,感觉写的不错,自己正好也在巩固下基础知识,虽然实际工作中用代理的模式的不是特别多,那是因为你使用的框架,已经帮你封装好了,所以,你可能感觉不到,但是感觉不到不但表不存在,了解下它的原理和使用场景还是能提高下逼格的。于是散仙总结了下文,还有一个实战小例子,用来帮助理解。下面开始:
一:什么是代理?
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
说白了,代理模式其实就相当于找房子时的中介,你无须找到真实的房东,就可以把租房子这件事给办了,而且因为中介,所以便有了一些额外增强的功能,所以少数中介会提高房价或黑你一下,当然咱们的程序肯定不是跟中介一个德行的。
二:java中代理的种类
(1)静态代理: 只能提供固定的类的代理,局限性比较大
(2)JDK动态代理:只能代理接口,通过反射,提高了灵活性,但性能稍慢
(3)CGLIB代理:Spring AOP的默认实现,可以代理类,无须提供对应接口,通过ASM(asm是Java字节码操控框架,ASM是一套java字节码生成架构,它可以动态生成二进制格式的stub类或其它代理类,或者在类被java虚拟机装入内存之前,动态修改类)字节码增强,速度要快于JDK的默认的动态代理。
三:使用代理的应用场景
这个问题,其实就跟问Spring AOP切面编程的好处,就非常类似了,通过代理模式,我们可以无侵入式的,很方便的实现日志记录功能,方法权限拦截功能,事务控制等功能。
四:实战例子
项目结构:
百度云盘下载: http://pan.baidu.com/s/1eQ0h5YE
1,JDK动态代理,模拟事务控制功能,已经记录方法的耗时功能
package com.easy.model; /*** * * @author qindongliang * */ public class Person { //用户名 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(String name) { super(); this.name = name; } public Person() { // TODO Auto-generated constructor stub } }
Dao接口已经实现类,里面含有测试的方法:
package com.easy.dao; import com.easy.model.Person; /*** * 动态代理测试dao * @author qindongliang * */ public interface PersonDao { //add user public void addUser(Person user); //delete user public void deleteUser(String name); //update user public void updateUser(String name); }
实现类:
package com.easy.dao.impl; import com.easy.dao.PersonDao; import com.easy.model.Person; /*** * Dao的实现类 * @author qindongliang * */ public class PersonDaoImpl implements PersonDao { @Override public void addUser(Person user) { // TODO Auto-generated method stub // System.out.println("add user name: "+user.getName()); try{ Thread.sleep(1000);//sleep 1 second }catch(Exception e){ e.printStackTrace(); } } @Override public void deleteUser(String name) { // System.out.println("delete user name: "+name); try{ Thread.sleep(1500);//sleep 1.5 second }catch(Exception e){ e.printStackTrace(); } } @Override public void updateUser(String name) { // System.out.println("update user name: "+name); try{ Thread.sleep(2000);//sleep 2 second }catch(Exception e){ e.printStackTrace(); } } }
JDK动态代理实现:
package com.easy.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; /*** * JDK动态代理例子 * @author qindongliang * */ public class JDK_Proxy implements InvocationHandler { //代理实例 private Object proxy; //通过构造参数赋值 public JDK_Proxy(Object proxy) { this.proxy = proxy; } //格式化时间 private static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj=null; //开始时间 long start=System.currentTimeMillis(); //以add开头的方法,加入事务控制 if(method.getName().startsWith("add")){ //开启事务 startTransaction(method); obj=method.invoke(this.proxy, args); //关闭事务 closeTransaction(method); }else{ obj=method.invoke(this.proxy, args); } //调用结束时间 long end=System.currentTimeMillis(); System.out.println(sdf.format(new Date())+" "+method.getName()+"调用方法执行时间为:"+(end-start)/1000+"秒!"); System.out.println(); return obj; } //模拟开启事务 public void startTransaction(Method method){ System.out.println("请注意:"+method.getName()+"开启了 commit 事务操作 !"); } //模拟关闭事务 public void closeTransaction(Method method){ System.out.println("请注意:"+method.getName()+"关闭了 commit 事务操作 !"); } }
无接口的cglib代理测试类:
package com.easy.dao.impl; /*** * 此类没有实现任何接口,只能使用Cglib代理来调用方法 * 必须有无参的构造方法 * @author qindongliang * */ public class CarManager { private String name; public CarManager() { // TODO Auto-generated constructor stub } public CarManager(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void run()throws Exception{ System.out.println(this.getName()+"汽车启动了!"); Thread.sleep(3000); } public void stop(){ System.out.println(this.getName()+"汽车停止了!"); } }
Cglib代理的实现:
package com.easy.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 qindongliang */ public class CGLIB_Proxy implements MethodInterceptor{ //代理对象 private Object target; @SuppressWarnings("unchecked") public static <T> T proxyTarget(T t) { Enhancer en = new Enhancer(); en.setSuperclass(t.getClass()); en.setCallback(new CGLIB_Proxy(t)); T tt = (T) en.create(); return tt; } public CGLIB_Proxy(Object target) { this.target = target; } @Override public Object intercept(Object arg0, Method method, Object[] args,MethodProxy arg3) throws Throwable { System.out.println("调用 "+method.getName()+" 开始...... "); //调用代理 Object obj=method.invoke(this.target, args); System.out.println("调用 "+method.getName()+" 结束...... "); return obj; } }
测试的代码:
package com.easy.main; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import com.easy.dao.PersonDao; import com.easy.dao.impl.CarManager; import com.easy.dao.impl.PersonDaoImpl; import com.easy.model.Person; import com.easy.proxy.CGLIB_Proxy; import com.easy.proxy.JDK_Proxy; /** * 包含jdk动态代理和cglib代理的测试 * @author qindongliang * */ public class MethodTest { public static void main(String[] args) throws Exception { //cglibProxyTest(); jdkProxyTest(); } /**** * cglib代理测试 */ public static void cglibProxyTest()throws Exception{ CarManager car=new CarManager("大众"); // // car.run(); // car.stop(); //得到代理类对象 CarManager carManager=CGLIB_Proxy.proxyTarget(car); carManager.run(); } /*** * jdk动态代理 */ public static void jdkProxyTest() { PersonDao user=new PersonDaoImpl(); Class<?> cls=user.getClass(); InvocationHandler handler=new JDK_Proxy(user); //转换得来的代理对象 PersonDao proxy=(PersonDao)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), handler); proxy.addUser(new Person("hadoop")); proxy.deleteUser("lucene"); proxy.updateUser("solr and elasticsearch"); } }
测试JDK动态代理结果:
测试cglib代理结果:
总结:使用代理模式,在一些场景,非常灵活,而且无侵入式的发挥巨大的作用,这就是面向切面编程的核心思想。
最后欢迎大家扫码关注微信公众号:我是攻城师(woshigcs),我们一起学习,进步和交流!(woshigcs)
本公众号的内容是有关搜索和大数据技术和互联网等方面内容的分享,也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!
参考文章:
http://andy136566.iteye.com/blog/967952
http://www.cnblogs.com/coderworld/p/java-reflect.html
http://blog.csdn.net/leon709/article/details/9529307
http://www.cnblogs.com/coderworld/p/java-dynamic-proxy.htm
发表评论
-
记一次log4j不打印日志的踩坑记
2019-09-22 01:58 1469### 起因 前几天一个跑有java应用的生产集群(200多 ... -
在Java里面如何解决进退两难的jar包冲突问题?
2019-07-23 19:10 1153如上图所示: es api组件依赖guava18.0 ... -
如何轻松理解二叉树的深度遍历策略
2019-07-03 23:33 1039我们知道普通的线性数据结构如链表,数组等,遍历方式单一 ... -
为什么单线程Redis性能也很出色
2019-01-21 18:02 2140高性能的服务器,不一 ... -
如何将编程语言里面的字符串转成数字?
2019-01-11 23:23 2008将字符串转成数字在很 ... -
为什么Java里面String类是不可变的
2019-01-06 18:36 1597在Java里面String类型是不可变对象,这一点毫无疑问,那 ... -
关于Java里面volatile关键字的重排序
2019-01-04 18:49 995Java里面volatile关键字主 ... -
多个线程如何轮流打印ABC特定的次数?
2018-12-11 20:42 5940之前的一篇文章,我给 ... -
聊聊Java里面的引用传递
2018-11-16 21:21 946长久以来,在Java语言里面一直有一个争论,就是Java语言到 ... -
理解计数排序算法的原理和实现
2018-10-11 10:03 2052计数排序(Counting sort) ... -
理解Java7和8里面HashMap+ConcurrentHashMap的扩容策略
2018-09-06 11:31 3348### 前言 理解HashMap和Con ... -
关于Java里面多线程同步的一些知识
2018-07-18 09:45 1072# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
Java单例模式之双检锁深入思考
2018-07-08 12:25 3254# Java单例模式之双检锁 ... -
关于Java里面多线程同步的一些知识
2018-07-08 12:23 1090# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
重新认识同步与异步,阻塞和非阻塞的概念
2018-07-06 14:30 1435# 重新认识同步与异步 ... -
线程的基本知识总结
2018-06-27 16:27 1028### (一)创建线程的方式 (1)实现Runnable接口 ... -
Java里面volatile关键字修饰引用变量的陷阱
2018-06-25 11:42 1333# Java里面volatile关键字修饰引用变量的陷阱 如 ... -
关于Java里面的字符串拼接,你了解多少?
2018-06-25 11:28 1325# 关于Java里面的字符串 ... -
深入理解Java内存模型的语义
2018-06-25 11:39 699### 前言 Java内存模型( ... -
如何证明Java多线程中的成员变量数据是互不可见的
2018-06-21 10:09 1462前面的几篇文章主要介绍了Java的内存模型,进程和线程的定义, ...
相关推荐
本人深圳安卓开发程序猿一枚,希望能一起...最近重温了一下java的设计模式,练练手,java设计模式有23种,写了12种常用的设计模式,一些觉得用不上就没写,水平有限,有问题欢迎留言一起加油email:674928145@qq.com!
所以,近段时间开始,将重温Java技术的基础知识,主版本为Java8,中间可能也会穿插一些其它版本,如Java7。谨以此系列文章,来记录重温Java基础的历程。 为啥费劲写这些文章?和写SpringCloud进阶之路时一样,一是...
NULL 博文链接:https://i8i8i8.iteye.com/blog/445946
在 C#中的委托和事件 一文的后半部分,我向大家讲述了Observer(观察者)模式,并使用委托和事件实现了这个模式。实际上,不使用委托和事件,一样可以实现Observer模式。在本文中,我将使用GOF的经典方式,再次实现一...
除了重温Java服务器面(JSF),它解释了为什么Facelets的,在JSF的现代版本引入的新功能,是首选的视图技术对Java服务器页面(JSP) 在后面的章节中探讨的竞争在Java WebSocket的标准实现,描述了JMS的更新;其目的...
有经验的开发者,希望重温Java基础知识或参考韩顺平的教学风格。 使用场景及目标 初学者入门:为无编程背景的学员提供Java语言的基础知识。 课程学习:作为计算机科学课程的辅助教材,帮助学生深入理解Java。 技能...
Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...
Java编程老鸟潜心写作,奉献高效率的Java学习心得 完全站在没有编程经验读者的角度,手把手教会读者学习Java 配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让...
重温微积分 - 齐民友
重温微积分前四章重排版齐民友.pdf
java基础教案,记得好像是大学的课件,是很好的入门教材。重温java基础就想起了这个课件。
同时在那个时间段,我正好重温了数据结构这本书。好像里面有提到银行。 所以当时就用java写了一段小程序来模拟窗口排队的情况。 有兴趣的朋友,看看下载下来看看。 我觉得可以利用这个程序可以帮助银行设立多少个...
在本例中,变量a与b对应位的组合代表了二进制数所有的 4 种组合模式:0-0,0-1,1-0 ,和1-1 。“|”运算符和“&”运算符分别对变量a与b各个对应位的运算得到了变量c和变量d的值。对变量e和f的赋值说明了“^”运算符...
微积分是科学与技术的基础。 本书对微积分起源、发展,特别是由于需求对微积分发展的推动,进行了重温。
重温微积分》根据作者多年来为各种不同程度的大学生和研究生讲课及讨论班上报告的内容整理而成。第一章对极限理论的发展作了历史的回顾。以下六章分别讨论函数、微分学、积分学、傅里叶分析、实分析与点集拓扑学基础...
重温老三篇心得体会精选13篇.doc
一款使用JAVA语言编写的猜数字的小游戏,很多电子词典上都有的,估计大家都玩过,让我们在来重温一遍吧!顺便看一下JAVA的源码!
齐民优经典微积分教程,打开新世界的大门!!相对于枯燥无味的高数教材,这本书能带来不一样的启发和更为深入地理解
java编写的坦克大战游戏,重温经典游戏。此项目完整的实现了坦克大战的游戏,非常适合开发者参考使用,也可以根据自己的喜好通过修改代码来实现各种关卡场景或者操作效果。
对于学过一点微积分知识的同学都可以尝试读一读,如果是数学专业的就更好地回味一下实分析的发展。