DAY11.3 Java核心基礎
反射(第三篇)
前兩篇我們學習了反射的概念和基本操作
實際開發中,反射應用于那里?
動態代理
java中的動態代理就是一個重要的作用
代理模式
代理模式是java中常用的設計模式
指的是在處理一個業務邏輯的時候通過代理的形式來完成,委托方委托代理方完成某些工作
委托方和代理方有一個共性:都具備完成業務的能力
代理分為委托方和代理方
委托方很好理解,代理方就把它想想為跑腿或者中介
靜態代理和動態代理
- 靜態代理:預先寫好代理類的方法,在編譯時期代理類的class文件就生成了
- 動態代理:在編譯時期沒有確定具體的代理類,在程序運行期間根據java代碼的指示動態生成
- 動態代理更加靈活,可以很方便了對代理類的方法進行統一的管理,不需要修改每一個代理類的方法
動態代理是通過反射機制實現的,所以動態代理是反射重要的應用之一
如何在java程序中表現出來呢?
在java中,我們把對象所具備的能力封裝為接口,所以java中代理模式就是委托類和代理類實現了相同的接口,代理類可以替代委托類完成一些業務以外的工作
代理類和委托類通過依賴注入的方式進行關聯,需要將委托類注入到代理類的成員變量
訪問委托類是通過代理類間接訪問的,所以可以為程序預留出可以處理的空間,可以在不影響原來的業務上擴展功能,這就是代理模式的優點
靜態代理
靜態代理模式示例(銷售手機):
銷售 iPhone 和華為手機
1、定義一個接口 Phone 表示銷售手機的功能
2、定義兩個類分別實現銷售 iPhone 和華為的功能
創建一個手機的接口來抽象銷售手機的方法
public interface Phone {public void salePhone();
}
實體類銷售蘋果手機
public class Apple implements Phone{@Overridepublic void salePhone() {System.out.println("銷售蘋果手機");}
}
實體類銷售華為手機
public class Huawei implements Phone{@Overridepublic void salePhone() {System.out.println("銷售華為手機");}
}
如果我們要實現更好的銷售量以及更好的管理那么可以使用到代理類,就相當于把東西交給中介來賣,這個手機中介可以銷售多款手機
創建一個PhoneProxy代理類來銷售手機:
public class PhoneProxy implements Phone{private Phone phone;public PhoneProxy(Phone phone) {this.phone = phone;}@Overridepublic void salePhone() {System.out.println("代理類,在這可以完成業務以外的工作");phone.salePhone();}
}
測試代碼:
public static void main(String[] args) {PhoneProxy proxy1 = new PhoneProxy(new Apple());proxy1.salePhone();PhoneProxy proxy2 = new PhoneProxy(new Huawei());proxy2.salePhone();}
}
代理銷售汽車案例:
創建Car對象
public interface Car{public void saleCar();
}
銷售寶馬車
public class BWM implements Car{@Overridepublic void saleCar() {System.out.println("銷售寶馬");}
}
銷售奔馳車
public class Benz implements Car{@Overridepublic void saleCar() {System.out.println("銷售奔馳車");}
}
測試:
public static void main(String[] args) {CarProxy carProxy1 = new CarProxy(new BWM());CarProxy carProxy2 = new CarProxy(new Benz());carProxy1.saleCar();carProxy2.saleCar();
}
可以實現銷售多款手機和汽車,可以在不影響委托類的業務基礎上擴展功能(比如統計買了幾臺手機…)
上述就是一個靜態代理,優勢在業務擴展的時候不需要修改委托類,只需要修改代理類的方法即可,在分離不同業務的同時保證代碼的整潔性
動態代理
現在的需求是創建一個廠商,既可以代理銷售手機又可以代理銷售汽車
怎么實現呢?
難道要注入兩個對象嗎,NoNoNo,這樣太不科學了
此時無法使用靜態代理,因為無論是 手機代理還是 汽車代理,都只能代理一種商品
靜態代理的問題就在于代理類已經寫好了,當需求變更的時候無法修改
類似這種問題,一個代理可以同時代理 N 種商品的模式,代理類就一定不能提前寫好,而是根據程序運行的具體情況動態生成的
代理對象,必須要創建,抽象類是無法創建對象的
代理類是不存在的,程序運行過程中動態創建一個類,從而創建該類對象,就叫做動態代理對象
動態代理的流程
1、只需要編寫委托類
2、不需要編寫代理類
3、程序運行過程中根據具體的需求動態創建一個代理類
4、根據動態創建出來的代理類來創建實例化對象
動態生成類的功能由誰來完成?
InvocationHandler 接口,通過該接口可以在程序運行期間動態生成代理類
根據委托對象創建動態代理對象
1、創建動態代理類
2、創建對象
代理類需要實現和委托類一樣的接口
根據委托類所實現的接口來創建代理類
類創建好之后需要加載到 JVM 中,由類加載器進行加載
public class MyInvocationHandler implements InvocationHandler {public Object obj;public Object bind(Object obj) {this.obj = obj;return Proxy.newProxyInstance(MyInvocationHandler.class.getClassLoader(),obj.getClass().getInterfaces(),this);}// 代理類代理的方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("這里是動態代理類,這里可以擴展方法");Object result = method.invoke(obj, args);return result;}
}
public static void main(String[] args) {MyInvocationHandler myInvocationHandler = new MyInvocationHandler();Car carProxy = (Car) myInvocationHandler.bind(new Benz());carProxy.saleCar();
}
輸出: