什么是動態代理?
接着之前的故事,我們繼續。我們在通過代購幫我們購買了好多次物品以后,代購現在越來越有錢了,代購的商品種類也更加豐富,他便自己開了一家代購公司D,這個時候我們如果想要去通過代購去買一件商品,就不在會是每一次都是同一個人去接待我們,可能是D公司的小劉美女業務員、也可能是小王帥哥業務員。即:動態代理就是,同一個服務由不同的實例去幫我們實現。
JDK動態代理類圖
JDK動態代理是如何實現的?
1、動態代理是由Proxy Java反射類提供實例創建的調派,由Proxy.newProxyInstance()方法幫我們創建對應的實例對象。
2、通過InvocationHandler接口中的invoke方法進行調用、增強、轉發實現業務。
為什么JDK中類的實例化以及業務實現如此復雜?
遵循Java單一原則,一個類或者一個接口只負責唯一職責,盡量設計出功能單一的接口。
代碼示例
A抽象對象
public interface ASellService {
void sale(String name);
}
A真實對象(商家A)
public class AMerchantServiceImplA implements ASellService {
@Override
public void sale(String name) {
System.out.println(name + "購買了A商品");
}
}
B抽象對象
public interface BSellService {
void sale(String name);
}
B真實對象(商家B)
public class BMerchantServiceImpl implements BSellService {
@Override
public void sale(String name) {
System.out.println(name + "購買了B商品");
}
}
JDK動態代理類(代理公司)
public class DCompany implements InvocationHandler {
// 代理對象需要包含真實對象,為提升真實對象的復用性,則使用Object接受
private Object objFactory;
public Object getObjFactory(){
return objFactory;
}
public void setObjFactory(Object objFactory){
this.objFactory = objFactory;
}
// 使用JDK代理類獲取代理對象
public Object getProxyInstance(){
return Proxy.newProxyInstance(objFactory.getClass().getClassLoader(), objFactory.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 進行業務增強
System.out.println("JDK動態代理對業務進行了增強處理");
// 通過反射調用方法本身
Object invoke = method.invoke(objFactory, args);
System.out.println("JDK動態代理對業務進行了增強處理結束");
return invoke;
}
}
測試類
public class DynamicProxyTest {
public static void main(String[] args) {
// A商品賣家
ASellService A = new AMerchantServiceImplA();
// B商品賣家
BSellService B = new BMerchantServiceImpl();
// 購買者
String customerName = "張三";
// 代購公司
DCompany dCompany = new DCompany();
dCompany.setObjFactory(A);
ASellService AProxyInstance = (ASellService) dCompany.getProxyInstance();
System.out.println("業務員"+AProxyInstance.getClass()+"接待"+customerName);
AProxyInstance.sale(customerName);
System.out.println("--------------------------------------------------------------");
dCompany.setObjFactory(B);
BSellService BProxyInstance = (BSellService) dCompany.getProxyInstance();
System.out.println("業務員"+BProxyInstance.getClass()+"接待"+customerName);
BProxyInstance.sale(customerName);
}
}
執行結果
我們可以清晰的看到JDK動態代理執行后打印的結果,以及Proxy動態調派幫我們由不同的代理對象$Proxy X實例化真實對象。
總結
1、動態代理無需真實對象的差異及數量可以統一的由代理方法幫我們創建對應的真實對象實例,並引用其中的方法。
2、動態代理屬於編譯期代理,及運行期代理。此特點則體現了實例對象的創建由Proxy進行調派完成實例化。
如果覺着不錯可以關注公眾號:Java禿頭猿,專注於項目實際開發技術分享。
java動態代理