Java基礎之讓你徹底搞懂代理模式
一、代理模式
什么是代理模式?
先來生活常用例子:你想買票,你沒必要去車站買;而是可以去一個代售點,代售點代理車站賣票,這就是一個簡單的代理模式!
- 主要解決:在直接訪問對象時帶來的問題,比如說:要訪問的對象在遠程的機器上。在面向對象系統(tǒng)中,有些對象由于某些原因(比如對象創(chuàng)建開銷很大,或者某些操作需要安全控制,或者需要進程外的訪問),直接訪問會給使用者或者系統(tǒng)結構帶來很多麻煩,我們可以在訪問此對象時加上一個對此對象的訪問層。
- 總結:我們訪問實例對象時是通過代理對象訪問的,這樣比較靈活也可以添加一些附加操作
二、靜態(tài)代理
顧名思義,靜態(tài)的,由程序員構寫,在編譯是就已經(jīng)將程序接口,代理類和被代理類寫定了!在程序運行前就已經(jīng)生成!
來個簡單實例:
設計公共接口Person:
public interface Person { public void handinWork(); }
Student:
public class Student implements Person { private String name; public Student(String name) { this.name=name; } public void setName(String name) { this.name = name; } public void handinWork() { System.out.println(name+"提交作業(yè)"); } }
代理類StudentProxy:
public class StudentProxy implements Person { //代理誰 Student student; //防止重名,確保只是代理Student這個對象 public StudentProxy(Student student) { if(student.getClass()==Student.class){ this.student = (Student) student; } } public void handinWork() { //交作業(yè)時代理(班長)想代替學生搞點事··· System.out.println("老師這個比的作業(yè)是抄的呢"); student.handinWork(); } }
測試:
public class StaticProxy { public static void main(String[] args) { //創(chuàng)建出兩個對象,代理和被代理 Student student = new Student("張三"); StudentProxy monitor = new StudentProxy(student); //代理類去交作業(yè)!?。。?! monitor.handinWork(); } }
可以發(fā)現(xiàn),程序本質還是學生交作業(yè),不過是通過一個中間層monitor(班長)去實現(xiàn)的,然后這個代理層還可以添加些其他的操作功能,在提交作業(yè)之前或者之后!
三、動態(tài)代理
靜態(tài)代理是在程序運行前就生成了,很明顯動態(tài)代理就是在程序運行期間添加代理層以達到效果。代理類動態(tài)生成!
- 需要了解兩個類:Proxy 代理, InvocationHandler
- Proxy:代理類,使用的時候動態(tài)生成
- InvocationHandler:主要執(zhí)行需要代理的方法,使用invoke執(zhí)行
舉個例子:方便理解,就上面那個實例我們將它改造成一個動態(tài)的!
第一步,創(chuàng)建一個類實現(xiàn)InvocationHandler接口,用它構建出代理類和代理方法:
public class ProxyInvocation implements InvocationHandler { //被代理的接口,真實的對象 private Person person; //生成得到的代理類 public void setPerson(Person person) { this.person = person; } //通過Proxy類的newProxyInstance方法創(chuàng)建代理對象,我們來看下方法中的參數(shù) // * 第一個參數(shù):people.getClass().getClassLoader(),使用handler對象的classloader對象來加載我們的代理對象 // * 第二個參數(shù):people.getClass().getInterfaces(),這里為代理類提供的接口是真實對象實現(xiàn)的接口,這樣代理對象就能像真實對象一樣調(diào)用接口中的所有方法 // * 第三個參數(shù):handler,我們將代理對象關聯(lián)到上面的InvocationHandler對象上 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),person.getClass().getInterfaces(),this); } //處理代理實例,返回結果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(person, args); return result; } }
參照靜態(tài)代理,需要一個代理對象,只不過靜態(tài)代理中代理對象是我們手動創(chuàng)建的,所以動態(tài)代理中我們利用jdk自帶代理類Proxy的newProxyInstance方法動態(tài)的生成了一個代理類而已,這個代理類可以根據(jù)我們傳的參數(shù)動態(tài)改變,
測試:
//真實角色student Student student = new Student("張三"); //拿到InvocationHandler的繼承類 ProxyInvocation pih = new ProxyInvocation(); //拿到代理的接口 pih.setPerson(student); //動態(tài)生成了proxy代理類 Person proxy = (Person) pih.getProxy(); //代理類執(zhí)行方法 proxy.handinWork();
改進成工具類:將獲得接口部分全部采用參數(shù)代替;
private Object target; //生成得到的代理類 public void setPerson(Object target) { this.target= target; } //通過Proxy類的newProxyInstance方法創(chuàng)建代理對象,我們來看下方法中的參數(shù) // * 第一個參數(shù):people.getClass().getClassLoader(),使用handler對象的classloader對象來加載我們的代理對象 // * 第二個參數(shù):people.getClass().getInterfaces(),這里為代理類提供的接口是真實對象實現(xiàn)的接口,這樣代理對象就能像真實對象一樣調(diào)用接口中的所有方法 // * 第三個參數(shù):handler,我們將代理對象關聯(lián)到上面的InvocationHandler對象上 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //處理代理實例,返回結果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(person, args); return result; }
就是把接口類型和參數(shù)改一下就可以!后續(xù)會添加代理模式在Spring上的使用,
四、總結
你不敲一遍代碼你永遠都不會理解,你抱著學一遍而不是徹底弄明白你也不可能學會!多查資料多理解代碼,多花點時間一定會懂得!加油老鐵。以解決問題的心態(tài)學編程而不是為了高薪工作。
到此這篇關于Java基礎之讓你徹底搞懂代理模式的文章就介紹到這了,更多相關java代理模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot實現(xiàn)rabbitmq消息確認的示例代碼
RabbitMQ的消息確認有兩種, 一種是消息發(fā)送確認,第二種是消費接收確認,本文主要介紹了springboot實現(xiàn)rabbitmq消息確認的示例代碼,具有一定的參考價值,感興趣的可以了解一下2023-09-09spring boot下 500 404 錯誤頁面處理的方法
本篇文章主要介紹了spring boot下 500 404 錯誤頁面處理的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04解決nacos啟動報錯Server check fail, please che
這篇文章主要介紹了nacos啟動 Server check fail, please check server localhost ,port 9848 is available的錯誤原因以及解決方法,需要的朋友可以參考下2023-09-09Jmeter多臺機器并發(fā)請求實現(xiàn)壓力性能測試
這篇文章主要介紹了Jmeter多臺機器并發(fā)請求實現(xiàn)壓力性能測試,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10