深入学习Java动态代理

  

<强>前言

  

要想了解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动态代理