即,動態代理是利用java反射技術,在運行時建立一個實現某些給定接口的新類。java
先定義接口api
public interface people { public String work(); }
實現該接口數組
public class Teacher implements people{ @Override public String work() { System.out.println("教書育人"); return "教書"; } }
編寫代理類ide
import com.sun.xml.internal.ws.api.pipe.FiberContextSwitchInterceptor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class WorkHandler implements InvocationHandler { // 代理類的對象 private Object obj; public WorkHandler(){ } // 在調用這個方法的時候,會被調度到invoke方法,並將參數傳入 public WorkHandler(Object obj){ this.obj = obj; } // 在調用給類的方法的時候,會被調度到invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 真實對象執行以前添加操做 // 調用obj類的method方法,而且參數爲args Object invoke = method.invoke(obj, args); // 真實對象執行後添加操做 return invoke;// 返回執行的結果 } }
最後運行函數
import java.io.FileInputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Main { public static void main(String[] args){ // 要代理的對象 people people = new Teacher(); // 建立要代理的真實對象 // 進行註冊 InvocationHandler handler = new WorkHandler(people); // 進行建立代理對象 // 定義一個代理對象 people proxy; // 調用Proxy.newProxyInstance方法 // 須要傳入真實對象實現的接口,爲下一步調用該方法作準備 // 將handler關聯到invocationHandler對象,用於調度到invoke方法 // 因爲返回的對象爲object類型,須要進行強制類型轉換,保留people接口定義的方法 // 最後一個參數要對對象進行關聯,最後批量生產出對象 proxy = (people) Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler); System.out.println(proxy.work()); } }
第一個參數是運行時,建立的代理對象。this
import java.io.FileInputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Main { // 須要使用static讓其加載進入內存 static class myClassLoader extends ClassLoader{ private String classPath; // 獲取當前類的在磁盤中保存的地址 // 經過構造函數將地址注入 public myClassLoader(String classPath){ this.classPath = classPath; } // 將文件內容加載進入內存 private byte[] loadByte(String name) throws Exception{ // 獲取一個輸入流, FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class"); // 獲取長度 int len = fis.available(); // 定義byte數組 byte[] data = new byte[len]; // 加載進入內存 fis.read(data); // 關閉流 fis.close(); return data; } // 重寫findClass方法,讓加載的時候調用findClass方法 protected Class<?> findClass(String name) throws ClassNotFoundException{ try{ // 讀取文件到數組中 byte[] data = loadByte(name); // 將字節碼加載進入內存當中 return defineClass(name, data, 0, data.length); }catch(Exception e){ e.printStackTrace(); } return null; } } public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException { // 先初始化該類 myClassLoader classLoader = new myClassLoader("/home/ming"); // 此時會調用findClass加載Test.class加載進入內存當中 Class clazz = classLoader.loadClass("com.ming.Test"); // 實例化該類對象 Object obj = clazz.newInstance(); // 獲取clazz該類方法中名稱爲hello,參數爲空的方法。 Method helloMethod = clazz.getDeclaredMethod("helloWorld", null); // 調用該方法 // 調用obj類中的helloMethod,參數爲空的方法。 helloMethod.invoke(obj, null); } }