1. 程式人生 > >實際專案中的spring的 DI 和 IOC

實際專案中的spring的 DI 和 IOC

前兩篇文章講到了專案用到的訊息中心和工作流模組,這篇文章來了解一下怎麼樣使用模組裡面的功能。


spring的核心是DI 和IOC,那到底什麼是DI(依賴注入)和IOC(控制反轉)呢,依賴在core java裡面講過,依賴是物件之間的關係,A物件依賴B物件,就是說A物件中有關於B物件的引用,比如說我們自己寫的類裡面需要輸入輸出,用到了InputStream或者是時間DateFormat,在我們使用這些工具類的時候我們都要例項化它們,這就是依賴。依賴注入我們就可以簡單的理解為,我們A物件依賴的B物件是Spring像打針一樣把B物件的例項注入到A物件中了,一想到打針就覺得屁股一陣酸爽。而我們都知道設計原則告訴我們,要依賴介面不要依賴實現類,這樣就降低了耦合,增加了靈活性,不得不說一個是實現類一個是介面,帶來了翻天覆地的變化。

而整個上面的過程即:A物件靠Spring的注入依賴B物件的過程,叫控制反轉。

用我們生活中的例子講:大熊想要造一座自己的房子(好開心),在沒有哆啦A夢(Spring)這個逆天的助手之前,他要自己買制磚機,水泥攪拌機等等工具(光聯絡廠家,決定什麼牌子就花費好多時間,而且房子造完之後這些大型機器就沒有用了)。但是自從有了哆啦A夢就不一樣啦,腰不疼了,腿不酸了,上樓梯不費勁!他只要告訴哆啦A夢自己需要一個能造磚頭的機器(我不管你是哪個牌子的),一個攪拌水泥的機器(我也不管是哪個牌子的),哆啦A夢就在自己的小口袋裡面找啊,找到以前自己裝進口袋的寶貝,翻出來一盒鹹魚,不是,一盒皮皮蝦,不是,一個不耐煩就給大熊一記大飛腳。最終找到了需要的機器,大熊造完房子之後哆啦A夢又把機器放回小口袋,是不是很方便。

那我們就看看原始碼中Bean的配置和依賴注入

首先我們知道Facade是提供對外能力輸入的介面,這個就要先放到Spring的小口袋裡:

//第一個Bean是具體的實現類

 <bean id="carrier_bidItemQueryFacade" class="com.opengroup.hongshi.carrier.biz.facadeimpl.bid.BidItemQueryFacadeImpl"></bean>

//第二個Bean是像容器中注入上面的實現類,注意,此處一起配置了介面和版本號。容器使用了Map,key就是介面名稱+版本號,而value就是包含介面資訊和版本號以及實現類的整個類。

    <bean id="bidItemQueryFacade_provider" class="com.opengroup.middleware.rpc.provider.FacadeProvider" init-method="init">
        <property name="delegateInterface" value="facade.bid.interfaces.BidItemQueryFacade"></property>
        <property name="version" value="0.0.1"></property>
        <property name="target" ref="bidItemQueryFacade"></property>
    </bean>

     String key = provider.getDelegateInterface() + "_" + provider.getVersion();
        if (pool.get(key) != null) {
            throw new CriticalSystemError("重複註冊服務導致系統無法啟動[" + key + "]");
        }
        pool.put(key, provider);

上面這個是Spring的bean的配置過程,寶貝已經放入Spring的小口袋裡面了,下面的工程需要使用這個寶貝的時候是按照能力(介面和版本)檢索的,比如需要實現了BidItemQueryFacade介面版本是0.0.1的實現類

 <bean id="bidItemQueryFacade_consumer" class="com.opengroup.middleware.rpc.consumer.FacadeConsumer">
        <property name="delegateInterface" value="facade.bid.interfaces.BidItemQueryFacade"></property>
        <property name="version" value="0.0.1"></property>
    </bean>
    <bean id="bidItemQueryFacade" factory-bean="bidItemQueryFacade_consumer" factory-method="init"></bean>
    <bean id="bidItemQueryFacadeClient" class="integration.BidItemQueryClientImpl">
        <property name="bidItemQueryFacade" ref="bidItemQueryFacade"></property>
    </bean>
    上面的配置就是先把需要的介面和版本號告訴工程類bidItemQueryFacade_consumer,然後用工程類init方法來生成具體的例項物件。(這裡面用到了發射和代理,很刺激)

第一個bean生成FacadeConsumer例項,並把我們希望的介面和版本號注入,

第二個bean就是用init方法生成具體的例項物件


            if (StringUtil.isBlank(version) || StringUtil.isBlank(delegateInterface)) {
                throw new CriticalSystemError("服務消費者,version[" + version + "]和delegateInterface["
                                              + delegateInterface + "]不可為空:");
            }
            if (proxyObj == null) {
                Class<?> delegateInterfaceCls = Class.forName(delegateInterface, false,
                    Thread.currentThread().getContextClassLoader())
;//Class.forName(delegateInterface);
                Class<?>[] tmp = new Class<?>[1];
                tmp[0] = delegateInterfaceCls;
                //                proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(), tmp, this);
                proxyObj = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    tmp, this);

            }
            return proxyObj;

我們看到這個地方實際上就是用到反射生成介面的例項,然後用到代理實現介面,

每次呼叫代理的方法時,我們就會

/**
     * 動態代理回撥介面
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
     */
    public Object invoke(Object proxy, Method method, Object[] args) {
        if (LogUtil.getUniqueId() == null) {
            LogUtil.myThreadStart(null);
        }

        FacadeProvider provider = null;
        switch (consumerType) {
            case JVM_LOCAL:
                provider = JvmFacadeProviderRegister.fetchProvider(delegateInterface, version);
                break;
            default:
                throw new RpcException("consumerType is not support:" + consumerType);
        }
        if (provider == null) {
            throw new RpcException(
                "找不到對應的服務提供者:interface[" + delegateInterface + "], version[" + version + "]");
        }
        String invoker = provider.getTarget().getClass().getName() + "." + method.getName() + "("
                         + consumerType.name() + ")";
        try {
            PerfLog.printStart(invoker);
            return method.invoke(provider.getTarget(), args);

、、我們看到代理回撥的時候,先找到我們之前注入的provider。然後找出具體實現類,呼叫method.invoke(provider.getTarget(), args)。

我們不得不佩服Spring在幫助我們完成自己的心願時付出的努力。也不得不佩服大熊有這麼好的夥伴

相關推薦

軌跡系列13——多軌跡展示在實際專案的落地優化

文章版權由作者李曉暉和部落格園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/ 1.背景          在之前的”多車輛實時跡展示方案”(https://www.cnblogs.com/naaoveGIS/p/8551915.html)文章中,我講解了我們

實際專案手動測試自動測試的合理運用

一、手動測試         手動測試,就是指完全依賴人工測試軟體,主要根據測試用例來執行測試,但是測試用例也不可能100%覆蓋軟體功能還要通過其他方式來發現軟體缺陷,這樣就要求測試人員的經驗要豐富並且具有發散思維的能力,通過錯誤猜測等方法來彌補測試用例沒有覆蓋的部分。 手

Amino在實際專案的安裝使用

Amino作為效能卓越的無鎖集合包,List執行緒安全集合執行速度之快遠超CopyOnRightArrayList,但它唯一的缺點

實際專案springDI IOC

前兩篇文章講到了專案用到的訊息中心和工作流模組,這篇文章來了解一下怎麼樣使用模組裡面的功能。 spring的核心是DI 和IOC,那到底什麼是DI(依賴注入)和IOC(控制反轉)呢,依賴在core java裡面講過,依賴是物件之間的關係,A物件依賴B物件,就是說A物件中有

用通俗的語言解釋 Spring DIIOC AOP概念

private rgs 完成 編程 而是 無需 解決 情況 分離關註點 DI 所謂依賴,從程序的角度看,就是比如A要調用B的方法,那麽A就依賴於B,反正A要用到B,則A依賴於B。所謂倒置,你必須理解如果不倒置,會怎麽著,因為A必須要有B,才可以調用B,如果不倒置,意思就是A

最全面的EventBus 3.1的使用教程及官方推薦的結合訂閱者索引processor顯著提升效能實際專案的使用注意事項

需求場景 無論是現在的專案還是以前的專案中,都會遇見執行緒之間通訊,元件之間通訊的需求,我們知道這些需求都可以使用EventBus來處理,為了對比體現出EventBus使用的方便簡潔,我們先來回顧下在EventBus出現以前我們是怎麼處理執行緒間通訊和元件間通訊的。 1,執行緒間通訊

Spark專案實戰-實際專案常見的優化點-分配更多的資源調節並行度

1、分配更多的資源 (1)分配哪些資源?executor、cpu per executor、memory per executor、driver memory。 (2)在哪裡分配這些資源?在我們在生產環境中,提交spark作業時,用的spark-submit shell指

Spring Boot 實踐 第六章 Spring data JAP在實際開發的封裝應用(上)

上一章簡單介紹了一下Spring boot和Spring Data JPA的整合和簡單使用.  但是在實際開發過程中, 我們發現Spring Data JPA提供的介面太簡單了,這樣就導致需要編寫大量的重複程式碼. 實際上Spring Data JPA提供了很多種擴充套件方

SpringDIIOC IOC實現方式

一.依賴注入和控制反轉 依賴注入(Dependecy Injection)和控制反轉(Inversion of Control)是同一個概念,具體的講:當某個角色 需要另外一個角色協助的時候,在傳統的程式設計過程中,通常由呼叫者來建立被呼叫者的例項。但在spri

Spring MVC實際專案的應用

目前的專案應用了Spring MVC框架,總結一下實際應用中這個框架是如何發揮作用的,下圖是處理流程。參考 1: 首先使用者傳送請求資訊,例如url:http://ggg-admin.inta.sit.fan.com/advertisement/query

實際專案使用poi匯出excel(spring+springMVC+Mybatis環境下)

1,需要匯出的原始資料.即根據實際需求查詢得到的結果集作為原始資料.可能是一個list,map...看你封裝成什麼樣了(這裡是封裝成list了) 2,將原始的資料轉換到excel中,具體根據資料形式不同,寫法也會不同.不過這些都是大同小異的. 3,將生產好的excel檔案寫到一個路徑下(這裡都是放到t

startActivityForResultsetResult在實際專案的用法舉例

 我們知道startActivityForResult( )較startActivity( )而言,不僅可以跳轉到下一個activity,而且當被跳轉的頁面呼叫finish()後,可以自動跳回

實際專案,看 ECharts HighCharts 渲染效能對比,表面看衣裝,本質看內功!!!

     最近做專案,使用的是echarts顯示圖表資料,但是資料量比較多的時候,有卡頓的情況。後來同事拿echarts和HighCharts做了對比,僅供大家參考。同時感謝同事做的工作。 一、查詢1天的源資料,屬性1、屬性2、屬性3、屬性4  &

Spring框架[一]——spring概念ioc入門(ioc操作xml配置文件)

修改 數組 名稱空間 springmvc jdbc ack 靜態 spring框架 鍵值 Spring概念 spring是開源的輕量級框架(即不需要依賴其他東西,可用直接使用) spring核心主要兩部分 aop:面向切面編程,擴展功能不是修改源代碼來

.Net Core DI使用 - IOC原則

fig rip assign 經典 快速 argument 好處 如圖所示 web api 概要:因為不知道寫啥,所以隨便找個東西亂說幾句,嗯,就這樣,就是這個目的。 1.IOC是啥呢?   IOC - Inversion of Control,即控制反轉的意思,這裏要

大話DI依賴注入+IOC控制反轉(二) 之 淺析.Net CoreDIIOC

      在上一篇文章中,我們聊了很多關於定義的方面,比較孤燥,下面我們結合.Net Core聊一下依賴注入&控制反轉。   三種物件生命週期       關於.Net Core中的容

Spring學習一(spring概念ioc入門)

  Spring概念     Spring是一個開源輕量級框架,Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Des

.net 一種新的傳參方式作為傳參的參考,很可能在實際專案使用

<asp:LinkButton ID="LinkButton1" runat="server" OnClientClick='<%# String.Format("return checkreturn(\"turnpost\",\"{0}

vue-cli搭建的專案引入jquerybootstrap

在專案初始化好之後,首先安裝jqury庫 cnpm install jquery -S 同時把bootstrap庫也一起安裝了,待會再一起配置 cnpm install [email protected] -S &n

springBoot專案的statictemplates資料夾

  記錄是為了更好的成長! 1、static檔案中的頁面 //這樣寫不能訪問static中index資料夾下的index.html頁面 @RequestMapping("index") public String hello() { return "/in