<强>前言强>
要想了解Java动态代理,首先要了解什么叫做代理,熟悉设计模式的朋友一定知道在Gof总结的23种设计模式中,有一种叫做代理(代理)的对象结构型模式,动态代理中的代理,指的就是这种设计模式。
在我看来所谓的代理模式,和23种设计模式中的“装饰模式”是一个东西23种设计模式中将它们作为两种模式,网上也有些文章讲这两种模式的异同,从细节来看,确实可以人为地区分这两种模式,但是抽象到一定高度后,我认为这两种模式是完全一样的。因此学会了代理模式,也就同时掌握了装饰模式。
<强>代理模式
强>
代理模式简单来说,就是对一个对象进行包装,包装后生成的对象具有和原对象一样的方法列表,但是每个方法都可以是被包装过的。
<强>静态代理强>
让我们先来看一段代码:
包普遍; 公共类测试{ 静态界面主题{ 空白sayHi (); 空白sayHello (); } 静态类SubjectImpl实现主题{ @Override 公共空间sayHi () { System.out.println(“嗨”); } @Override 公共空间sayHello () { System.out.println(“hello”); } } 静态类SubjectImplProxy实现主题{ 私人主体目标; 公共SubjectImplProxy(主题目标){ this.target=目标; } @Override 公共空间sayHi () { System.out.print(“说:”); target.sayHi (); } @Override 公共空间sayHello () { System.out.print(“说:”); target.sayHello (); } } 公共静态void main (String [] args) { 主题主题=new SubjectImpl (); 主题subjectProxy=new SubjectImplProxy(主题); subjectProxy.sayHi (); subjectProxy.sayHello (); } } >之前这段代码中首先定义了一个话题接口,接口中有两个方法。
然后定义了SubjectImpl类实现主题接口并实现其中的两个方法,到这里肯定是没问题的。
现在再定义一个SubjuectImplProxy类,也实现主题接口。这个SubjectImplProxy类的作用是包装SubjectImpl类的实例,它的内部定义一个变量目标来保存一个SubjectImpl的实例.SubjectImplProxy也实现了接口规定的两个方法,并且在它的实现版本中,都调用了SubjectImpl的实现,但是又添加了自己的处理逻辑。
相信这段代码不难理解,它通过对SubjectImpl进行包装,达到了给输出内容添加前缀的功能。这种代理方式叫做静态代理。
<强>动态代理
强>从上面的演示中我们不难看出静态代理的缺点:我们对SubjectImpl的两个方法,是进行的相同的包装,但是却要在SubjectImplProxy里把相同的包装逻辑写两次,而且以后如果主题接口再添加新的方法,SubjectImplProxy也必须要添加新的实现,尽管SubjectImplProxy对所有方法的包装可能都是一样的。
下面我把上面例子的静态代理改成动态代理,我们来看一下区别:
包普遍; 进口java.lang.invoke.MethodHandle; 进口java.lang.reflect.InvocationHandler; 进口java.lang.reflect.Method; 进口java.lang.reflect.Proxy; 公共类测试{ 静态界面主题{ 空白sayHi (); 空白sayHello (); } 静态类SubjectImpl实现主题{ @Override 公共空间sayHi () { System.out.println(“嗨”); } @Override 公共空间sayHello () { System.out.println(“hello”); } } 静态类ProxyInvocationHandler实现InvocationHandler { 私人主体目标; 公共ProxyInvocationHandler(主题目标){ this.target=目标; } @Override 公共对象调用对象代理、方法方法,对象[]args)抛出Throwable { System.out.print(“说:”); 方法返回。调用(目标,args); } } 公共静态void main (String [] args) { 主题主题=new SubjectImpl (); 主题subjectProxy=(主题)Proxy.newProxyInstance (subject.getClass () .getClassLoader (), subject.getClass () .getInterfaces(),新的ProxyInvocationHandler(主题); subjectProxy.sayHi (); subjectProxy.sayHello (); } } >之前只看主方法的话,只有第二行和之前的静态代理不同,同样是生成一个subjectProxy代理对象,只是生成的代码不同了。静态代理是直接新一个SubjectImplProxy的实例,而动态代理则调用了java.lang.reflect.Proxy.newProxyInstance()方法,我们来看一下这个方法的源码:
深入学习Java动态代理