吃透動態代理,解密spring AOP源碼(二)

緊接着上節,爲了解決靜態代理的問題,出現了動態代理, 假設動態代理是一個代購公司,私有變量Object factory爲動態生成的具體的真實對象,可代購對應的產品 。代碼:ide

/**
 * 動態代理
 */
public class DynamicProxyCompanyC implements InvocationHandler {

    // 被代理的對象,即真實對象
    private Object factory;

    public Object getFactory() {
        return factory;
    }

    public void setFactory(Object factory) {
        this.factory = factory;
    }

    // 經過proxy獲取動態代理的對象
    public Object getProxyInstance() {
    //第三個參數是InvocationHandler,傳入自身說明此proxy對象是和自身的invoke方法合做的,代理對象方法調用會通過下面invoke的加強


        return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), this);
    }

    @Override
     /**經過動態代理對象對方法進行加強
 *  @param proxy 代理對象
 *  @param method 要加強的方法(攔截的方法)
 *  @param args 方法參數
 */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        dosomeThingBefore();
        Object ret = method.invoke(factory, args);// 經過反射機制調用方法
        dosomeThingAfter();
        return ret;
    }

    public void dosomeThingBefore() {
        System.out.println("售前服務,負責產品調研,興趣愛好");
    }

    public void dosomeThingAfter() {
        System.out.println("售後服務,包裝丶送貨上門一條龍服務");
    }
}

測試類:測試

public class Proxytest {

    public static void main(String[] args) {
        // 代購公司C,負責代購全部產品
        DynamicProxyCompanyC proxy = new DynamicProxyCompanyC();
        // 日本有家A公司生產男性用品
        ManToolFactory dogToolFactory = new AManFactory();
        // 代購A公司的產品
        proxy.setFactory(dogToolFactory);
        // 建立A公司的代理對象
        ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance();
        // 代理對象完成代購男性用品
        proxyObject.saleManTool("D");
        System.out.println("--------------");
        // 日本有家B公司生產女性用品
        WomanToolFactory womanToolFactory = new BWomanFactory();
        // 代購B公司的產品
        proxy.setFactory(womanToolFactory);
        // 建立B公司的代理對象
        WomanToolFactory proxyObject1 = (WomanToolFactory) proxy.getProxyInstance();
        // 代理對象完成代購女性用品
        proxyObject1.saleWomanTool(1.8);
    }
}
// 售前服務,負責產品調研,興趣愛好
// A工廠出售男性用品,D罩杯
// 售後服務,包裝丶送貨上門一條龍服務
// --------------
// 售前服務,負責產品調研,興趣愛好
// B工廠生產女性用品,長度1.8米
// 售後服務,包裝丶送貨上門一條龍服務
  • 動態代理解決了上節說的開閉原則,那麼接下來咱們要解密動態代理的原理,重點類DynamicProxyCompanyC

1.實現了InvocationHandler接口;this

2.經過proxy獲取動態代理的對象。spa

根據咱們此例子裏面來講,動態代理就相似一個代購公司,可代購全部產品,須要購買哪一個產品的時候就實例化一個真實對象(如測試類須要男性用品則將接口引用指向真實對象AManFactory),根據真實對象建立代理對象來執行具體的方法,圖解以下:代理

clipboard.png

clipboard.png

Proxy:

接下來咱們先初步看一下JDK裏面的Proxy這個源碼。
這個註釋是說Proxy提供個一個靜態方法來建立代理類和代理實例,它也是全部由此方法建立的代理類的父類。
靜態方法建立代理實例即方法newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h);調試

InvocationHandler :

InvocationHandler 是一個接口,定義了invoke(Object proxy, Method method, Object[] args)方法code

總的來講Proxy專門負責new一個實例(真實對象),而具體方法作什麼,業務怎樣加強就由InvocationHandler(抽象對象)的invoke方法(抽象對象即接口定義的方法)來決定。對象

接下來咱們要搞清楚動態代理的底層原理,首先咱們調試一下test類,會發現 ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance()中建立的proxyObject 對象類名是$Proxy0,是ManToolFactory接口的實現類。可是咱們項目工程裏面卻沒有$Proxy0這個類,那它到底是怎麼出現的,下節講解。接口

相關文章
相關標籤/搜索