1. 程式人生 > 實用技巧 >Java代理之動態代理

Java代理之動態代理

什麼是動態代理?

接著之前的故事,我們繼續。我們在通過代購幫我們購買了好多次物品以後,代購現在越來越有錢了,代購的商品種類也更加豐富,他便自己開了一家代購公司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動態代理