当前位置: 移动技术网 > IT编程>开发语言>Java > Java Proxy机制详细解读

Java Proxy机制详细解读

2019年07月19日  | 移动技术网IT编程  | 我要评论

 动态代理其实就是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和反射机制代码分析等,有什么问题可以随时留言,小编会及时回复大家。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网