反射與動態代理
阿新 • • 發佈:2019-01-05
反射是動態語言的關鍵,動態代理正是通過反射實現
一.靜態代理:
靜態代理是通過構建代理類物件,將被代理類物件以引數的形式傳遞給代理類物件,進而在代理類物件中呼叫被代理類的方法。
程式碼實現如下:
1.建立介面
2.定義被代理類實現介面
3.定義代理類,通過代理類的構造方法為其被代理類物件屬性賦值,代理類的productCloth()方法實際呼叫的是被代理類物件的方法
4.建立main方法測試
package D19; /** * @Author: wj * @Date: 2018/12/1 16:19 * @Version 1.0 * * 靜態代理演示 * 使用一個代理類將物件包裝起來,然後用該代理物件取代原始物件,任何對原始物件的呼叫 * 都要通過代理,代理物件決定是否以及何時將方法呼叫轉到原始物件上 */ /** *介面 */ interface ClothFactory{ public void productCloth(); } /** *被代理類 */ class NikeClothFactory implements ClothFactory{ public void productCloth() { System.out.println("NIKE"); } } /** * 代理類 */ class ProxyFactory implements ClothFactory{ ClothFactory cf ; /**建立代理類物件時,實際傳入的是被代理類物件 * @param cf(多型) */ public ProxyFactory(ClothFactory cf){ this.cf=cf; } public void productCloth() { cf.productCloth(); } } public class TestStaticAgent { public static void main(String[] args) { NikeClothFactory nikeClothFactory = new NikeClothFactory(); //建立被代理類物件 //代理類物件 ProxyFactory proxyFactory = new ProxyFactory(nikeClothFactory); //建立代理類物件 //雖然執行的是代理類的productCloth();但實際呼叫的是被代理類的productCloth()方法 proxyFactory.productCloth(); } }
5.輸出:
二.動態代理
動態代理比靜態代理更加自如,不必考慮代理類接受物件的型別,具有更加自如地靈活性,實現了動態程式碼
步驟與靜態代理相同
1.定義介面
2.定義實現介面的被代理類
3.定義實現了InvocationHandler介面的代理類,定義blind方法接受被代理類物件(作用有兩個1.為屬性賦值,2返回實現了被代理類所實現介面的代理類物件),實現了invoke方法,該方法實際就是被帶了類的方法
程式碼如下:
package D19; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @Author: wj * @Date: 2018/12/2 13:38 * @Version 1.0 * * 動態代理的使用 */ //介面 interface Subject{ void action(); } /** * 被代理類 */ class RealSubject implements Subject{ public void action() { System.out.println("被代理類執行"); } } /** * 代理類 */ class MyInvocationHandler implements InvocationHandler{ Object object;//實現了介面的被代理類物件的宣告(RealSubject) // 1.給被代理類的物件例項話 //2.返回一個代理類的物件 public Object blind(Object obj){ this.object = obj; //三個引數被代理類物件的classLoader,被代理類實現的介面,實現了InvocationHandler介面的類物件 return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this); } //當通過代理類的物件發起對被代理類方法的呼叫時,都會轉為對invoke方法的呼叫,進而實現動態效果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //returnVal是被代理類方法的返回值 Object returnVal = method.invoke(object,args); System.out.println("invoke方法被呼叫"); return returnVal; } } public class TestDynamicAgent { public static void main(String[] args) { //1.構造被代理類的物件 RealSubject realSubject = new RealSubject(); //2建立一個實現了InvocationHandle介面的物件 MyInvocationHandler myInvocationHandler = new MyInvocationHandler(); //3.通過myInvocationHandle的blind方法 ,返回實現了被代理類所實現的介面的代理類物件 Object obj = myInvocationHandler.blind(realSubject); Subject sub = (Subject) obj;//sub就是i代理類的物件 sub.action();//轉到對代理類的inovke方法的呼叫 // //測試動態代理 // NikeClothFactory clothFactory = new NikeClothFactory(); // Object demo = myInvocationHandler.blind(clothFactory); // ClothFactory clo = (ClothFactory) demo; // clo.productCloth(); } }
輸出:
在main方法中還寫了一個測試,具體的應用了動態代理。