舉例理解JDK動態代理
JDK動態代理
說到java自帶的動態代理api,肯定離不開反射。JDK的Proxy類實現動態代理最核心的方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
這個方法的作用:在執行時,動態建立一組指定介面的實現類物件。其中的三大引數:
-
ClassLoader loader
- 類載入器,主要作用是用來載入類的,把.class檔案載入到jvm的方法區中,形成class物件
-
Class<?>[] interfaces
- 實現的介面列表
-
InvocationHandler h
- InvocationHandler 是一個介面,裡面有且只有一個方法invoke(Object proxy, Method method, Object[] args),後面會介紹。
我們可以先看個簡單的例子:
public class DynamicProxyDemo { @Test public void test1() { ClassLoader loader = this.getClass().getClassLoader(); Class[] classes = {Human.class, Car.class}; InvocationHandler h = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("來了,老弟~"); return null; } }; Human human = (Human) Proxy.newProxyInstance(loader, classes, h); human.male(); human.toString(); human.getClass(); } } interface Human { Object male(); } interface Car { Object bmw(); }
輸出:
來了,老弟~ 來了,老弟~
可以看到,程式碼並沒有報錯,因為Proxy.newProxyInstance(loader, classes, h)返回的物件是實現了指定介面的類物件,所以強轉成Human沒有問題,當呼叫Human物件的方法時,會執行InvocationHandler裡的invoke方法的語句。但是我當我呼叫getClass()方法時,並沒有執行對應的語句,這是由於此方法是native方法,是呼叫本地的方法。
既然呼叫代理物件的所有方法(個別除外)都會呼叫某個方法(invoke()),我們可以在裡面進行任意操作,達到前置或者後置增強的效果。
未完待續。