【java】說說有關jdk動態代理的那些事

首先說下爲何要有動態代理呢?設計模式中,有一種模式叫代理模式,爲何要使用動態代理其實和爲何要使用設計模式同樣,請讀者自行思考。

代理一般有靜態代理,動態代理,其中靜態代理是經過持有目標對象引用,而後對目標對象的方法進行加強,能夠說是一種硬編碼。jdk動態代理也須要持有目標對象的引用,在目標對象的方法的調用處進行加強,但這部分被封在處理器InvocationHandler中,經過反射機制生成Proxy實例,並傳入處理器。----先來看下使用jdk動態代理實現方式:java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy implements InvocationHandler {
  private Object target;
  public DynamicProxy(Object object){
   this.target = object;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("before......");
    Object result = method.invoke(target,args);
    System.out.println("after......");
    return result;
  }
  @SuppressWarnings("unchecked")
  public <T> T getProxy(){
    return (T)Proxy.newProxyInstance(
         target.getClass().getClassLoader(),
         target.getClass().getInterfaces(),
          this);
  }
}

動態是相對於靜態代理而言,jvm執行java類,須要先將class文件加載到jvm中,java是不容許在運行時修改class文件的,因此要想使用動態代理,須要動態生成class文件,加載到jvm中。經過設置系統屬性,能夠在運行時看到jdk動態生成的class文件。spring

System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
在生成的類文件中,能夠看到代理類繼承自Proxy並實現了業務自定義的接口,下面是動態生成的代理類部分代碼:
public final class $Proxy0 extends Proxy implements IHello{
 public final String hello(String var1) throws  {
    return (String)super.h.invoke(this, m3, new Object[]{var1});
  }
  static {
    m0 = Class.forName("java.lang.Object").getMethod("hashCode");
   m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
   m2 = Class.forName("java.lang.Object").getMethod("toString");
   m3 = Class.forName("com.proxy.IHello").getMethod("hello", Class.forName("java.lang.String"));
  }
}
能夠看到jdk動態代理生成的代碼,將目標對象接口的全部方法進行了代理,目標方法的執行就變成了處理器的invoke,在invoke中已經對目標對象中進行了加強。
其實思路是樸素的,就比如你不想出去吃飯點了外賣,外賣就至關於你的代理,幫你送飯,可是吃飯仍是須要你本身來,外賣平臺已經知道你須要的加強就是有人送飯,而後動態給你指定一個外賣騎手......----
下面看下jdk動態代理爲了生成代理類是如何操做的,首先查找或生成設計好的代理class:

圖片

由ProxyClassFactory在給定類加載器和接口數組的條件下,生成、定義、並返回代理class。
設計模式

圖片

最後將class字節碼加載到jvm,在生成代理類的函數中能夠看到是否生成class文件的布爾標記saveGeneratedFiles:數組

圖片

jdk動態代理無處不在,大名鼎的spring AOP默認使用的就是jdk動態代理,對於沒有接口實現的類才使用cglib代理。jvm

相關文章
相關標籤/搜索