Spring中AOP的底層原理就是動態代理模式,所以我們在這裡對代理模式進行學習。 一、代理模式 1.什麼是代理 代理,顧名思義,就是一個人代替另一個人去做他需要做的事情。代理是一種設計模式,具體實現就是一個類代替某個類去實現功能。 我們舉一個例子: 我要租房子,我可以找房東直接租房子。同樣我可以找 ...
Spring中AOP的底層原理就是動態代理模式,所以我們在這裡對代理模式進行學習。
一、代理模式
1.什麼是代理
代理,顧名思義,就是一個人代替另一個人去做他需要做的事情。代理是一種設計模式,具體實現就是一個類代替某個類去實現功能。
我們舉一個例子:
我要租房子,我可以找房東直接租房子。同樣我可以找中介來租房子,這個中介就是代理,它代理房東來做租賃房子的事情。
2.為什麼需要代理模式呢?
我們的開發一般都是縱向開發,當有新的需求出現但又不想改變原有的業務邏輯時,就需要用到代理模式了,代理模式屬於橫向開發,我們只需要代理原來的業物邏輯併在代理類中添加新的功能即可。
二、靜態代理
1.定義一個介面;
2.被代理類實現介面;
3.代理類引用被代理類,並且通過被代理類的方法實現介面。
我們以上圖為例子,來進行一個靜態代理的簡單應用:
1.定義一個rental介面
package com.jms.demo01; //租房介面 public interface rental { void doRental(); }
2.被代理類landlord實現介面
package com.jms.demo01; //房東 public class landlord implements rental{ @Override public void doRental() { System.out.println("房東要出租房子"); } }
3.代理類intermediary引用被代理類,並且通過被代理類的方法實現介面。
package com.jms.demo01; //中介 public class intermediary implements rental{ private landlord landlord; public intermediary(landlord landlord) { this.landlord = landlord; } @Override public void doRental() { landlord.doRental(); seeHouse(); writeContract(); } public void seeHouse() { System.out.println("中介帶你看房子"); } public void writeContract() { System.out.println("中介和你簽合同"); } }
同時代理類可以根據實際需求添加自己的方法。
4.測試一下
package com.jms.demo01; //租客 public class Tenants { public static void main(String[] args) { landlord landlord = new landlord(); intermediary intermediary = new intermediary(landlord); intermediary.doRental(); } }
三、動態代理
上面靜態代理的缺陷很明顯,一個代理類對應一個被代理類,當我們的被代理類數量相當龐大時,我們也要寫出相應的數量的代理類才行,為瞭解決這個問題,我們就需要用到動態代理。
我們再以上面租房為例用動態代理實現。
1.介面還是上面的rental介面;
2.代理類landlord實現介面與靜態代理相同;
3.動態代理沒有代理類,而是通過java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy來實現
具體寫法如下:
package com.jms.demo3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyInvocationHandler implements InvocationHandler { //被代理的介面 private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理類 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //處理代理實例並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { java.lang.Object result = method.invoke(target, args); seeHouse(); writeContract(); return result; } }
這段代碼適用於任何介面的動態代理,即拿即用。
我們在上面類中可以隨意添加我們需要的方法,此處我將其修改如下:
package com.jms.demo3; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyInvocationHandler implements InvocationHandler { //被代理的介面 private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理類 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //處理代理實例並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { java.lang.Object result = method.invoke(target, args); seeHouse(); writeContract(); return result; } public void seeHouse() { System.out.println("中介帶你看房子"); } public void writeContract() { System.out.println("中介和你簽合同"); } }
4.具體的使用
public class Tenants { public static void main(String[] args) { //被代理類 landlord landlord = new landlord(); ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(); //設置動態代理的介面 proxyInvocationHandler.setTarget(landlord); //獲取介面 rental rental = (rental) proxyInvocationHandler.getProxy(); //執行具體操作 rental.doRental(); } }
(本文僅作個人學習記錄用,如有紕漏敬請指正)