`

浅谈java中的代理+即将工作一年感想

 
阅读更多

还有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,而Spring2大核心之一是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的动态代理有一个特别明显的不足,即只能对接口实现动态代理。cglibCode 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动态代理的区别

1JDK动态代理只能对接口实现动态代理,而cglib能对类实现动态代理

2JDK动态代理生成动态代理类的速度或者说效率要比cglib快,但是生成后的动态代理类的效率则是cglib高,一般会高十倍以上,所以如果在Spring中使用动态代理,而Spring中的实例一般都是单例的,所以在Spring中生成动态代理类实例一般选用cglib比较好。这样生成的动态代理类的实例效率高。

闲扯几句:一般类的信息、常量信息会放在jvm内存中的方法区或者说是永久区,如果生成动态代理类过多的话,该区被占用的也就越多,有可能导致该区域的内存溢出(只是有可能,现实当中出现的几率非常小,就顺嘴提一句)。

  • 大小: 41.4 KB
6
9
分享到:
评论
13 楼 haoran_10 2013-07-25  
知识概括的比较全面了,
12 楼 牛奶123 2013-07-12  
状态很好!继续保持!
11 楼 Shen.Yiyang 2013-07-11  
kjmmlzq19851226 写道
  补充一下楼主的闲扯几句 permgen space在运行时不会gc,所以说会导致内存溢出,判断条件就是permgen space的占用大小是否已经超过了jvm的maxpermsize。那什么情况是最容易导致内存溢出呢?个人觉得热部署很有希望成为这个始作俑者,如果在重新部署时不删除原来的class那么就会造成permgen space一直增大,最终到达jvm的maxpermsize从而溢出。

这种情况,如果能选择模块化技术,就方便多了,不然自己处理调优非常麻烦。
10 楼 bluend1004 2013-07-09  
挺好的,不过纠正一点,常量进本会放在栈里,生命周期短,读取方便;编译后或者动态代理生成的类信息会放在永久区中,如果满了,的确会引起full gc,当然咱可以通过jvm调优来尽力避免这一情况的发生!
9 楼 ddlgyq 2013-07-08  
lvwenwen 写道
工作一年,就成技术牛人了?发生什么了,让你成长这么快?

我不是技术牛人,只是得到牛人的认可,我自己离牛人还差的远呢
8 楼 lvwenwen 2013-07-08  
工作一年,就成技术牛人了?发生什么了,让你成长这么快?
7 楼 ddlgyq 2013-07-08  
求求你帮帮我 写道
工作一年,就成技术牛人了?发生什么了,让你成长这么快?

我不是牛人,还差的远呢 只不过牛人对我的进步表示了赞同
6 楼 kjmmlzq19851226 2013-07-08  
  补充一下楼主的闲扯几句 permgen space在运行时不会gc,所以说会导致内存溢出,判断条件就是permgen space的占用大小是否已经超过了jvm的maxpermsize。那什么情况是最容易导致内存溢出呢?个人觉得热部署很有希望成为这个始作俑者,如果在重新部署时不删除原来的class那么就会造成permgen space一直增大,最终到达jvm的maxpermsize从而溢出。
5 楼 求求你帮帮我 2013-07-08  
工作一年,就成技术牛人了?发生什么了,让你成长这么快?
4 楼 ddlgyq 2013-07-08  
jinnianshilongnian 写道
加油    

谢谢~共勉
3 楼 jinnianshilongnian 2013-07-08  
加油    
2 楼 ddlgyq 2013-07-08  
rlplyyrb 写道
激情能持续多久呢?

不知道,目前还是蛮有激情的,努力坚持吧
1 楼 rlplyyrb 2013-07-08  
激情能持续多久呢?

相关推荐

Global site tag (gtag.js) - Google Analytics