欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java Proxy机制详细解读

程序员文章站 2024-02-25 10:49:04
 动态代理其实就是java.lang.reflect.proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承proxy类,并实现所...

 动态代理其实就是java.lang.reflect.proxy类动态的根据您指定的所有接口生成一个class byte,该class会继承proxy类,并实现所有你指定的接口(您在参数中传入的接口数组);然后再利用您指定的classloader将 class byte加载进系统,最后生成这样一个类的对象,并初始化该对象的一些值,如invocationhandler,以即所有的接口对应的method成员。 初始化之后将对象返回给调用的客户端。这样客户端拿到的就是一个实现你所有的接口的proxy对象。请看实例分析:

一  业务接口类

public interface businessprocessor {
 public void processbusiness();
}

二 业务实现类

public class businessprocessorimpl implements businessprocessor {
 public void processbusiness() {
 system.out.println("processing business.....");
 }
}

三 业务代理类

import java.lang.reflect.invocationhandler;
import java.lang.reflect.method;
public class businessprocessorhandler implements invocationhandler {
 private object target = null;
 businessprocessorhandler(object target){
 this.target = target;
 }
 public object invoke(object proxy, method method, object[] args)
  throws throwable {
 system.out.println("you can do something here before process your business");
 object result = method.invoke(target, args);
 system.out.println("you can do something here after process your business");
 return result;
 }
}

四 客户端应用类

import java.lang.reflect.field;
import java.lang.reflect.method;
import java.lang.reflect.modifier;
import java.lang.reflect.proxy;
public class test {
 public static void main(string[] args) {
 businessprocessorimpl bpimpl = new businessprocessorimpl();
 businessprocessorhandler handler = new businessprocessorhandler(bpimpl);
 businessprocessor bp = (businessprocessor)proxy.newproxyinstance(bpimpl.getclass().getclassloader(), bpimpl.getclass().getinterfaces(), handler);
 bp.processbusiness();
 }
}

现在我们看一下打印结果:

you can do something here before process your business
processing business.....
you can do something here after process your business

通过结果我们就能够很简单的看出proxy的作用了,它能够在你的核心业务方法前后做一些你所想做的辅助工作,如log日志,安全机制等等。

现在我们来分析一下上面的类的工作原理。

类一二没什么好说的。先看看类三吧。 实现了invocationhandler接口的invoke方法。其实这个类就是最终proxy调用的固定接口方法。proxy不管客户端的业务方法是怎么实现的。当客户端调用proxy时,它只会调用invocationhandler的invoke接口,所以我们的真正实现的方法就必须在invoke方法中去调用。关系如下:

 businessprocessorimpl bpimpl = new businessprocessorimpl();
 businessprocessorhandler handler = new businessprocessorhandler(bpimpl);
businessprocessor bp = (businessprocessor)proxy.newproxyinstance(....);
bp.processbusiness()-->invocationhandler.invoke()-->bpimpl.processbusiness();

那么bp到底是怎么样一个对象呢。我们改一下main方法看一下就知道了:

 public static void main(string[] args) {
 businessprocessorimpl bpimpl = new businessprocessorimpl();
 businessprocessorhandler handler = new businessprocessorhandler(bpimpl);
 businessprocessor bp = (businessprocessor)proxy.newproxyinstance(bpimpl.getclass().getclassloader(), bpimpl.getclass().getinterfaces(), handler);
 bp.processbusiness();
 system.out.println(bp.getclass().getname());
 }

输出结果:

you can do something here before process your business
processing business.....
you can do something here after process your business
$proxy0

bp原来是个$proxy0这个类的对象。那么这个类到底是长什么样子呢?好的。我们再写二个方法去把这个类打印出来看个究竟,是什么三头六臂呢?我们在main下面写如下两个静态方法。

public static string getmodifier(int modifier){
 string result = "";
 switch(modifier){
  case modifier.private:
  result = "private";
  case modifier.public:
  result = "public";
  case modifier.protected:
  result = "protected";
  case modifier.abstract :
  result = "abstract";
  case modifier.final :
  result = "final";
  case modifier.native :
  result = "native";
  case modifier.static :
  result = "static";
  case modifier.synchronized :
  result = "synchronized";
  case modifier.strict :
  result = "strict";
  case modifier.transient :
  result = "transient";
  case modifier.volatile :
  result = "volatile";
  case modifier.interface :
  result = "interface";
 }
 return result;
 }
 public static void printclassdefinition(class clz){
 string clzmodifier = getmodifier(clz.getmodifiers());
 if(clzmodifier!=null && !clzmodifier.equals("")){
  clzmodifier = clzmodifier + " ";
 }
 string superclz = clz.getsuperclass().getname();
 if(superclz!=null && !superclz.equals("")){
  superclz = "extends " + superclz;
 }
 class[] interfaces = clz.getinterfaces();
 string inters = "";
 for(int i=0; i<interfaces.length; i++){
  if(i==0){
  inters += "implements ";
  }
  inters += interfaces[i].getname();
 }
 system.out.println(clzmodifier +clz.getname()+" " + superclz +" " + inters );
 system.out.println("{");
 field[] fields = clz.getdeclaredfields();
 for(int i=0; i<fields.length; i++){
  string modifier = getmodifier(fields[i].getmodifiers());
  if(modifier!=null && !modifier.equals("")){
  modifier = modifier + " ";
  }
  string fieldname = fields[i].getname();
  string fieldtype = fields[i].gettype().getname();
  system.out.println("  "+modifier + fieldtype + " "+ fieldname + ";");
 }
 system.out.println();
 method[] methods = clz.getdeclaredmethods();
 for(int i=0; i<methods.length; i++){
  method method = methods[i];
  string modifier = getmodifier(method.getmodifiers());
  if(modifier!=null && !modifier.equals("")){
  modifier = modifier + " ";
  }
  string methodname = method.getname();
  class returnclz = method.getreturntype();
  string retruntype = returnclz.getname();
  class[] clzs = method.getparametertypes();
  string paralist = "(";
  for(int j=0; j<clzs.length; j++){
  paralist += clzs[j].getname();
  if(j != clzs.length -1 ){
   paralist += ", ";
  }
  }
  paralist += ")";
  clzs = method.getexceptiontypes();
  string exceptions = "";
  for(int j=0; j<clzs.length; j++){
  if(j==0){
   exceptions += "throws ";
  }
  exceptions += clzs[j].getname();
  if(j != clzs.length -1 ){
   exceptions += ", ";
  }
  }
  exceptions += ";";
  string methodprototype = modifier +retruntype+" "+methodname+paralist+exceptions;
  system.out.println("  "+methodprototype );
 }
 system.out.println("}");
 }

再改写main方法

 public static void main(string[] args) {
 businessprocessorimpl bpimpl = new businessprocessorimpl();
 businessprocessorhandler handler = new businessprocessorhandler(bpimpl);
 businessprocessor bp = (businessprocessor)proxy.newproxyinstance(bpimpl.getclass().getclassloader(), bpimpl.getclass().getinterfaces(), handler);
 bp.processbusiness();
 system.out.println(bp.getclass().getname());
 class clz = bp.getclass();
 printclassdefinition(clz);
 }

现在我们再看看输出结果:

you can do something here before process your business
processing business.....
you can do something here after process your business
$proxy0
$proxy0 extends java.lang.reflect.proxy implements com.tom.proxy.dynamic.businessprocessor
{
  java.lang.reflect.method m4;
  java.lang.reflect.method m2;
  java.lang.reflect.method m0;
  java.lang.reflect.method m3;
  java.lang.reflect.method m1;
  void processbusiness();
  int hashcode();
  boolean equals(java.lang.object);
  java.lang.string tostring();
}

很明显,proxy.newproxyinstance方法会做如下几件事:

1,根据传入的第二个参数interfaces动态生成一个类,实现interfaces中的接口,该例中即businessprocessor接口的processbusiness方法。并且继承了proxy类,重写了hashcode,tostring,equals等三个方法。具体实现可参看 proxygenerator.generateproxyclass(...); 该例中生成了$proxy0类

2,通过传入的第一个参数classloder将刚生成的类加载到jvm中。即将$proxy0类load

3,利用第三个参数,调用$proxy0的$proxy0(invocationhandler)构造函数 创建$proxy0的对象,并且用interfaces参数遍历其所有接口的方法,并生成method对象初始化对象的几个method成员变量

4,将$proxy0的实例返回给客户端。
现在好了。我们再看客户端怎么调就清楚了。

1,客户端拿到的是$proxy0的实例对象,由于$proxy0继承了businessprocessor,因此转化为businessprocessor没任何问题。

businessprocessor bp = (businessprocessor)proxy.newproxyinstance(....);

2,bp.processbusiness();

实际上调用的是$proxy0.processbusiness();那么$proxy0.processbusiness()的实现就是通过invocationhandler去调用invoke方法啦!

总结

以上就是本文关于java proxy机制详细解读的全部内容,希望对大家有所帮助。感兴趣的朋友可以参阅:、关于java反射机制 你需要知道的事情java的rtti和反射机制代码分析等,有什么问题可以随时留言,小编会及时回复大家。