浅谈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内存中的方法区或者说是永久区,如果生成动态代理类过多的话,该区被占用的也就越多,有可能导致该区域的内存溢出(只是有可能,现实当中出现的几率非常小,就顺嘴提一句)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值