真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例

這篇文章主要講解了“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例”吧!

創(chuàng)新互聯(lián)專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、夏縣網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)、購物商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為夏縣等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

1、Dubbo的IOC例子

@Test
public void test1(){
    ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
    AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");
    URL url = URL.valueOf("test://localhost/test");
    adaptiveExtension.echo("d", url);
}

public class DubboAdaptiveExt implements AdaptiveExt {

    // dubbo中有依賴AdaptiveExt類型的變量
    private AdaptiveExt adaptiveExt;

    public void setAdaptiveExt(AdaptiveExt adaptiveExt) {
        this.adaptiveExt = adaptiveExt;
    }

    @Override
    public String echo(String msg, URL url) {
        System.out.println(this.adaptiveExt.echo(msg, url));
        return "dubbo";
    }
}
// 此時(shí)ThriftAdaptiveExt上面是標(biāo)注了@Adaptive注解的
@Adaptive
public class ThriftAdaptiveExt implements AdaptiveExt {
    @Override
    public String echo(String msg, URL url) {
        return "thrift";
    }
}

2、Dubbo的IOC需要用到的ExtensionFactory

Spring的IOC中,給生成的bean注入依賴,是調(diào)用context.getBean(name)去獲得要注入的bean.Dubbo的IOC類似,它通過ExtensionFactory類型的變量objectFactory去dubbo中獲取bean,核心代碼objectFactory.getExtension(pt, property).下面先分析一下objectFactory的創(chuàng)建過程.objectFactory需要用到SpringExtensionFactory和SpiExtensionFactory.先看一下ExtenionFactory的實(shí)現(xiàn)類,如下圖.下面通過源碼分析objectFactory的生成過程.

Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例

這里的getExtensionLoader()詳細(xì)分析可以參見: Dubbo的SPI機(jī)制分析1-SPI加載class

ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);

public static  ExtensionLoader getExtensionLoader(Class type) {
    // 刪去一些不必要的代碼,詳細(xì)分析可以看前面幾篇分析
    // 從緩存中獲取與拓展類對應(yīng)的ExtensionLoader
    ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
    if (loader == null) {
        // 若緩存未命中,則創(chuàng)建一個(gè)新的實(shí)例,創(chuàng)建新的實(shí)例時(shí)會走
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
        loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
    }
    return loader;
}

 private ExtensionLoader(Class type) {
    this.type = type;
    // 這里的type是AdaptiveExt.class,所以會執(zhí)行后面的代碼,加載并創(chuàng)建SpiExtensionFactory和SpringExtensionFactory
    objectFactory = (type == ExtensionFactory.class ? null : 
	                     ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
public T getAdaptiveExtension() {
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {
        if (createAdaptiveInstanceError == null) {
            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        // 創(chuàng)建自適應(yīng)拓展代理類對象并放入緩存,這里創(chuàng)建的就是ExtensionFactory的自適應(yīng)拓展對象
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        // 拋異常
                    }
                }
            }
        }
    }
    return (T) instance;
}
 private T createAdaptiveExtension() {
    try {
        // 分為3步:1是創(chuàng)建自適應(yīng)拓展代理類Class對象,2是通過反射創(chuàng)建對象,3是給創(chuàng)建的對象按需依賴注入
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {
        // 拋異常
    }
}

getExtensionClasses()方法詳細(xì)分析可以參見: Dubbo的SPI機(jī)制分析1-SPI加載class

private Class getAdaptiveExtensionClass() {
    // 這里前面文章已經(jīng)分析過了,它會去加載默認(rèn)目錄下的ExtensionFactory的實(shí)現(xiàn)類,總共有3個(gè),目錄是
    // META-INF/dubbo/internal/,該目錄對應(yīng)兩個(gè)文件,文件內(nèi)容見下,由于AdaptiveExtensionFactory上面
    // 標(biāo)注了@Adaptive注解,所以它優(yōu)先級最高,它就是ExtensionFactory的默認(rèn)實(shí)現(xiàn)類
    getExtensionClasses();
    // 如果有標(biāo)注了@Adaptive注解實(shí)現(xiàn)類,那么cachedAdaptiveClass不為空,直接返回
    if (cachedAdaptiveClass != null) {
        // 這里直接返回,cachedAdaptiveClass = AdaptiveExtensionFactory.class
        return cachedAdaptiveClass;
    }
    // 不會再走這一步
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
文件1內(nèi)容:
// 其中AdaptiveExtensionFactory上面標(biāo)注了@Adaptive注解
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory

文件2內(nèi)容:
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
// 分析完了getAdaptiveExtensionClass(),它是返回AdaptiveExtensionFactory,接下來newInstance會調(diào)用它默認(rèn)的構(gòu)造方法
return injectExtension((T) getAdaptiveExtensionClass().newInstance());

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
    // 里面維護(hù)SpringExtensionFactory和SpiExtensionFactory
    private final List factories;

    public AdaptiveExtensionFactory() {
        ExtensionLoader loader = 
                                    ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List list = new ArrayList();
        for (String name : loader.getSupportedExtensions()) {
            // 分別給SpringExtensionFactory和SpiExtensionFactory創(chuàng)建對象并放入list中
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }
}

3、Dubbo的IOC源碼分析

// 上面已經(jīng)分析過了第一行代碼,這里面會創(chuàng)建ExtensionFactory類型的變量objectFactory,這里面維護(hù)了一個(gè)list,
// list里面有SpringExtensionFactory和SpiExtensionFactory類型的實(shí)例,Dubbo的IOC獲取bean就是通過這兩個(gè)變量去獲取的
ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");

public T getExtension(String name) {
    // 刪去一些代碼
    if (instance == null) {
        synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
                // 創(chuàng)建拓展實(shí)例
                instance = createExtension(name);
                holder.set(instance);
            }
        }
    }
    return (T) instance;
}
private T createExtension(String name) {
    // 從配置文件中加載所有的拓展類,可得到“配置項(xiàng)名稱”到“配置類”的映射關(guān)系表
    // 這里我們指定了名字dubbo,并不是通過getAdaptiveExtension方法去獲得自適應(yīng)拓展類,這點(diǎn)要區(qū)分
    // 所以這里拿到的是com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt
    Class clazz = getExtensionClasses().get(name);
    if (clazz == null) {
        throw findException(name);
    }
    try {
        // 也是嘗試先從緩存獲取,獲取不到通過反射創(chuàng)建一個(gè)并放到緩存中
        T instance = (T) EXTENSION_INSTANCES.get(clazz);
        if (instance == null) {
            // 這里直接通過反射創(chuàng)建DubboAdaptiveExt的實(shí)例,然后給他依賴注入
            EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
            instance = (T) EXTENSION_INSTANCES.get(clazz);
        }
        
        // 依賴注入
        injectExtension(instance);
        
        return instance;
    } 
}
private T injectExtension(T instance) {
 // 這里為了排版好看,刪去一些異常捕捉拋出代碼
 // objectFactory就是我們前面分析的,它里面維護(hù)了SpringExtensionFactory和SpiExtensionFactory類型的實(shí)例
 if (objectFactory != null) {
    // 遍歷DubboAdaptiveExt實(shí)例的所有方法,尋找set開頭且參數(shù)為1個(gè),且方法權(quán)限為public的方法
    for (Method method : instance.getClass().getMethods()) {
        if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
                                               && Modifier.isPublic(method.getModifiers())) {
            
            // 獲取參數(shù)類型,這里是AdaptiveExt.class
            Class pt = method.getParameterTypes()[0];
            
            // 獲取屬性名,這里是adaptiveExt
            String property = method.getName().length() > 3 ? 
                              method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
            // 獲取容器中AdaptiveExt.class類型的名字為adaptiveExt的實(shí)例
            Object object = objectFactory.getExtension(pt, property);
            // 獲取之后通過反射賦值
            if (object != null) {
                 method.invoke(instance, object);
            }
         }   
    }
 }
 return instance;
}
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List factories;

    @Override
    public  T getExtension(Class type, String name) {
        // 遍歷factory中所有的ExtensionFactory,先從SpiExtensionFactory中獲取,獲取不到在去Spring容器中獲取
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }
}

這里獲取自適應(yīng)拓展可以參考: Dubbo的SPI機(jī)制分析2-Adaptive詳解

public class SpiExtensionFactory implements ExtensionFactory {
    @Override
    public  T getExtension(Class type, String name) {
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader loader = ExtensionLoader.getExtensionLoader(type);
            if (!loader.getSupportedExtensions().isEmpty()) {
                // 先看SpiExtensionFactory怎么獲取,它是通過getAdaptiveExtension()去自適應(yīng)獲取,根本
                // 沒有用到name,所以這里返回ThriftAdaptiveExt的實(shí)例
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }
}
public class SpringExtensionFactory implements ExtensionFactory {
    // 可以看到Spring是先根據(jù)名字去取,取不到再根據(jù)類型去取
    @Override
    public  T getExtension(Class type, String name) {
        for (ApplicationContext context : contexts) {
            if (context.containsBean(name)) {
                Object bean = context.getBean(name);
                if (type.isInstance(bean)) {
                    return (T) bean;
                }
            }
        }

        for (ApplicationContext context : contexts) {
            try {
                return context.getBean(type);
            }
        }
        return null;
    }
}
// 所以這段代碼輸出:thrift
@Test
public void test1(){
    ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
    AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");
    URL url = URL.valueOf("test://localhost/test");
    adaptiveExtension.echo("d", url);
}

4、測試通過URL依賴注入

 /**
 * 測試通過URL依賴注入,將ThriftAdaptiveExt類上面的注解注釋掉,同時(shí)給AdaptiveExt方法加上注解@Adaptive("t")
 */
@Test
public void test5(){
    ExtensionLoader loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);

    Map map = new HashMap<>();
    // t這個(gè)key就是根據(jù)@Adaptive("t")定的,兩者要一致
    map.put("t", "cloud");
    URL url = new URL("", "", 1, map);
    AdaptiveExt adaptiveExtension = loader.getExtension("dubbo");
    adaptiveExtension.echo(" ", url);
}

上述代碼輸出spring cloud,創(chuàng)建完DubboAdaptiveExt的實(shí)例給其注入依賴時(shí),調(diào)用injectExtension(instance),因?yàn)闆]有了@Adaptive標(biāo)注的類,所以需要Dubbo自己生成自適應(yīng)拓展代理類Class,生成過程可以參考: Dubbo的SPI機(jī)制分析2-Adaptive詳解.生成的代理類中有這樣一句關(guān)鍵代碼: String extName = url.getParameter("t", "dubbo"),因?yàn)閡rl中有這個(gè)t參數(shù),所以最后會調(diào)用cloud所對應(yīng)的SpringCloudAdaptiveExt的echo方法,輸出spring cloud.

感謝各位的閱讀,以上就是“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!


網(wǎng)頁題目:Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴注入實(shí)例
標(biāo)題路徑:http://weahome.cn/article/jehjeh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部