还有20天 ,就工作一年了,感觉时间过得真快,当然有的时候也会觉得时间过得很慢,当然觉得慢的时候是觉得怎么离发工资还有那么久的时间,回顾这一年的时间,从刚开始的生手到现在得到一个技术牛人的认可,经历了很多。当然,能让自己进步唯有学习。。自己本身非常喜欢技术,不是很喜欢管理,觉得管理人员的事比较多,比较杂,比较费心、劳心,所以以后还是想走技术路线,争取早日实现自己的一个目标-成为架构师。废话不多说了,今天就来说说代理--proxy
java中的代理按照代理类的生成时期不同分为静态代理和动态代理。
(1)静态代理。由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。下面是静态代理的UML图。
具体的代码如下
1. interface Subject 2. { 3. void request(); 4. } 5. class RealSubject implements Subject 6. { 7. public void request() 8. { 9. System.out.println("真实的请求"); 10. } 11. } 12. public class Proxy implements Subject 13. { 14. RealSubject realSubject; 15. public void request() 16. { 17. if(realSubject==null) 18. { 19. realSubject=new RealSubject(); 20. } 21. realSubject.request(); 22. } 23. 24. public static void main(String[] args) { 25. new Proxy().request(); 26. } 27. }
(2)动态代理。动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性。想必做java web开发的,会经常用到Spring,而Spring的2大核心之一是Spring AOP,Spring AOP就是利用动态代理实的(Spring利用动态代理技术实现的最重要的一个功能就是声明式事务)。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。那么接下来就利用动态代理实现上面的例子
1. import java.lang.reflect.InvocationHandler; 2. import java.lang.reflect.Method; 3. import java.lang.reflect.Proxy; 4. 5. interface Subject { 6. void request(); 7. } 8. 9. class RealSubject implements Subject { 10. public void request() { 11. System.out.println("真实的请求"); 12. } 13. } 14. 15. public class DynProxy implements InvocationHandler { 16. 17. private Object dele; 18. 19. public DynProxy(Object obj) { 20. this.dele = obj; 21. } 22. 23. public Object invoke(Object proxy, Method method, Object[] args) 24. throws Throwable { 25. doBefore(); 26. // 在这里完全可以把下面这句注释掉,而做一些其它的事情 27. Object result = method.invoke(dele, args); 28. after(); 29. return result; 30. } 31. 32. private void doBefore() { 33. System.out.println("before...."); 34. } 35. 36. private void after() { 37. System.out.println("after...."); 38. } 39. 40. public static void main(String[] args) { 41. RealSubject realSubject= new RealSubject(); 42. DynProxy dynProxy= new DynProxy(realSubject); 43. Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), dynProxy); 44. subject.request(); 45. } 46. }
这是JDK的动态代理,JDK的自动代理只能对接口实现自动代理,从代码当中也可以看出来realSubject.getClass().getInterfaces().JDK动态对接口进行实现,实现的方法是个空方法,那么动态代理又是怎么调用的realSubject相对应的实现方法呢,答案就是InvocationHandler,它关联了实现类,在上面的例子中也就是realSubject,它会调用realSubject相对应的实现方法。
JDK的动态代理有一个特别明显的不足,即只能对接口实现动态代理。cglib(Code Generation Library)的出现则弥补了JDK代理的不足,cglib能够实现对类进行动态代理。下面就用cglib来实现上面的例子。
1. import java.lang.reflect.Method; 2. import net.sf.cglib.proxy.Enhancer; 3. import net.sf.cglib.proxy.MethodInterceptor; 4. import net.sf.cglib.proxy.MethodProxy; 5. 6. class RealSubject { 7. public void request() { 8. System.out.println("真实的请求"); 9. } 10. private void privateExample(){ 11. System.out.println("这个是私有方法不能被子类继承"); 12. } 13. 14. } 15. 16. public class MyMethodInterceptor implements MethodInterceptor { 17. 18. public Object intercept(Object object, Method method, Object[] args, 19. MethodProxy methodProxy) throws Throwable { 20. System.out.println(">>>MethodInterceptor start..."); 21. Object result = methodProxy.invokeSuper(object, args); 22. System.out.println(">>>MethodInterceptor ending..."); 23. return "hahahh"; 24. } 25. 26. public Object createProxy(Class targetClass) { 27. Enhancer enhancer = new Enhancer(); 28. enhancer.setSuperclass(targetClass); 29. enhancer.setCallback(new MyMethodInterceptor()); 30. return enhancer.create(); 31. } 32. 33. public static void main(String[] args) { 34. RealSubject target = new RealSubject(); 35. MyMethodInterceptor test = new MyMethodInterceptor(); 36. RealSubject proxyTarget = (RealSubject)test.createProxy(RealSubject.class); 37. proxyTarget.request(); 38. } 39. }
cglib能实现对类的动态代理,产生的动态代理类是原始类,在上面的例子就是RealSubject的子类,那么又跑回到了java继承体系当中了,private方法 final方法是不能被子类继承和override的,所以这些方法是不会被动态代理的。像上面的方法privateExample(),就不会出现在main函数中的proxyTarget的方法列表中。
JDK动态代理和cglib动态代理的区别
1、JDK动态代理只能对接口实现动态代理,而cglib能对类实现动态代理
2、JDK动态代理生成动态代理类的速度或者说效率要比cglib快,但是生成后的动态代理类的效率则是cglib高,一般会高十倍以上,所以如果在Spring中使用动态代理,而Spring中的实例一般都是单例的,所以在Spring中生成动态代理类实例一般选用cglib比较好。这样生成的动态代理类的实例效率高。
闲扯几句:一般类的信息、常量信息会放在jvm内存中的方法区或者说是永久区,如果生成动态代理类过多的话,该区被占用的也就越多,有可能导致该区域的内存溢出(只是有可能,现实当中出现的几率非常小,就顺嘴提一句)。
相关推荐
追究海尔这一年-海尔工作一年后的感想所写原文 word 版。追究海尔这一年-海尔工作一年后的感想所写原文 word 版。追究海尔这一年-海尔工作一年后的感想所写原文 word 版。追究海尔这一年-海尔工作一年后的感想所写...
“互联网+”背景下大学生创新创业工作的感想.pdf“互联网+”背景下大学生创新创业工作的感想.pdf“互联网+”背景下大学生创新创业工作的感想.pdf“互联网+”背景下大学生创新创业工作的感想.pdf“互联网+”背景下大...
“互联网+”背景下大学生创新创业工作的感想.docx“互联网+”背景下大学生创新创业工作的感想.docx“互联网+”背景下大学生创新创业工作的感想.docx“互联网+”背景下大学生创新创业工作的感想.docx“互联网+”背景...
高手的指点会让新手少走不少冤枉路哟,所以新手可以看看这个
在圈子信息框中,用户可以发布信息,即在生活中所看见的关于动物的状况等,可发布之间的感想以及救助动物的今后的生活分享等等; 在志愿者中,用户填写完个人信息以及表明志愿工作内容,和志愿工作时间,同时可以...
心得,体会,感想,实习,实训,项目。项目实训实习心得体会感想范文(适用于Java和数据库实训其他实训也可参考用语)
浅谈对《计算机应用基础》教学的感想 摘要:针对计算机文化基础课程改革实践中存在的某些问题,文章总结了在课程体系、 教学内容、教学方法、教学手段及教学模式等试点实践方面的经验,在一定范围推广实践 表明,取得...
在圈子信息框中,用户可以发布信息,即在生活中所看见的关于动物的状况等,可发布之间的感想以及救助动物的今后的生活分享等等; 在志愿者中,用户填写完个人信息以及表明志愿工作内容,和志愿工作时间,同时可以...
好东西大家分享——JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看JAVA连连看
李兴华老师学习java的感受,希望有迷茫的同志看看李老师的理解,加深学习动力
对JAVA程序设计的感想.pdf
五子棋 大学Java课程设计 eclipse编写和运行 五子棋 大学Java课程设计 eclipse编写和运行
“它”更简单,java很容易学习和使用,它丢弃了C++中难理解的令人迷惑的特性。
新入职护士工作感想精选.doc
项目管理工作心得感想工作心得体会.pdf
非常实用的eclipse快捷键,还有一大波Java初学者必须看的基础知识。以及一些个人学习Java中理解的部分。
律师工作心得感想.doc
企业工作心得感想.doc