[轉]深刻理解Java Proxy機制

該文章轉自網絡,原文不可考,給出轉載文章連接:http://blog.csdn.net/rokii/article/details/4046098java

 

看項目代碼看到一段寫的很美的代理機制,整理一下:數組

  動態代理其實就是java.lang.reflect.Proxy類動態的根據您指定的全部接口生成一個class byte,該class會繼承Proxy類並實現全部你指定的接口(您在參數中傳入的接口數組);而後再利用您指定的classloader將 class byte加載進系統,最後生成這樣一個類的對象,並初始化該對象的一些屬性,如invocationHandler,以及全部的接口對應的Method成員。 初始化以後將對象返回給調用的客戶端。這樣客戶端拿到的就是一個實現你全部的接口的Proxy對象。請看實例分析:安全

 

業務接口網絡

public interface BusinessProcessor {
 public void processBusiness();
}

 

業務接口實現類jvm

public class BusinessProcessorImpl implements BusinessProcessor {
   public void processBusiness() {
    System.out.println("processing business.....");
   }
}

 

業務代理類ide

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(); } }

打印結果:this

You can do something here before process your business
processing business.....
You can do something here after process your businessspa

 經過結果咱們就可以很簡單的看出Proxy的做用了,它可以在你的核心業務方法先後作一些你所想作的輔助工做,如log日誌,安全機制等等。.net

 

如今咱們來分析一下上面的類的工做原理。

類一二沒什麼好說的。

先看看類三吧:實現了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("}");
 }
View Code

 

再改寫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類load3,利用第三個參數,調用$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方法啦!

相關文章
相關標籤/搜索