Spring Framework之IoC容器





Spring IoC 概述

問題

1.什么是依賴倒置?

2.什么是控制反轉?

3.什么是依賴注入?

4.它們之間的關系是怎樣的?

5.優點有哪些?

依賴倒置原則 (Dependency Inversion Principle)

依賴倒置是一種設計原則。

​ 依賴倒置包括三層含義:(1)高層模塊不應該直接依賴於底層模塊,兩者都應依賴其抽象;(2)抽象不應依賴於細節;(3)細節應該依賴於抽象。

控制反轉 (Inversion of Control)

控制反轉是一種思想。其核心思想在於,合作的對象依賴關系的管理不由具體對象來完成,而是具體對象交出依賴關系的控制權,由第三方容器來集中管理。

​ 第三方容器管理的優點:(1)依賴關系的集中管理,關系清晰且易管理;(2)降低合作對象之間的耦合程度。

​ 舉個栗子。我想在北京租一間房子,我只需要把我的需求告知鏈家等中介公司,通過他們整合的資源,我就能夠找到一間符合我需求的房子。我不需要與房東產生任何直接的關系,中間的任何問題都由鏈家進行統一處理。在這個例子中,房客與房東是兩個獨立的對象,而鏈家則是充當中間容器

依賴注入(Dependency Inversion)

依賴注入是控制反轉的具體方法之一。依賴注入就是將底層依賴對象以參數形式傳入上層對象。

​ 對象間的依賴關系的管理被反轉至IoC容器中。對象間的依賴關系由IoC容器進行統一管理,並由IoC容器來完成對象的注入。

依賴倒置原則 、控制反轉 、依賴注入的關系

DIP、IoC、DI關系圖

優點

1.實現模塊間松耦合

2.由IoC容器來統一管理依賴關系,對象從復雜的依賴關系中解放。

3.對象自身弄夠專注於自身功能上,不需要了解依賴對象的內部結構。



IoC 容器

BeanFactory3

BeanFactory

BeanFactory4

BeanFactory提供最基本的IoC容器功能和基本規范。

​ BeanFactory中有getBean、getType、getAliases、isSingleton、isPrototype等函數。主要常用接口是getBean,改函數能夠通過Bean名稱獲取Bean

BeanFactory擴展接口

(1)ListableBeanFactory:接口定義Bean的基本信息。

​ 接口中函數有:getBeanDefinitionCount獲取Bean數量、containsBeanDefinition判斷容器中是否存在該Bean、getBeanDefinitionNames獲取工程所有Bean的名稱等。

(2)HierarchicalBeanFactory:父子容器關聯

​ 接口中函數有:getParentBeanFactory子容器可以通過函數訪問到父容器

(3)ConfigurableBeanFactory:可定制IoC容器

​ 接口中函數有:setBeanClassLoader設置Bean類加載器、setBeanExpressionResolver設置表達式解析器、registerCustomEditor注冊編輯器等。

(4)AutowireCapableBeanFactory:定義Bean自動裝配規則

​ 接口中函數有:autowireBeanProperties根據名稱或屬性給Bean進行自動裝配等。

ApplicationContext

ApplicationContext關系圖

ApplicationContext基於BeanFactory,是比BeanFactory更為高級的容器。

​ ApplicationContext相對於BeanFactory提供更多功能,BeanFactory中需要通過編程實現的功能,ApplicationContext中可以使用配置來實現。

​ ApplicationContext繼承ListableBeanFactory、HierarchicalBeanFactory,除此之外還擴展了其他接口。

ApplicationContext擴展接口:

(1)ApplicationEventPublisher:封裝事件發布功能。

(2)MessageSource:提供i18n國際化消息剛問功能。(解釋模塊中解釋i18n)

(3)ResourcePatternResolver:通過路徑加載資源

(4)LifeCycle:start()、stop()、isRunning(),控制與判斷容器當前狀態,以達到控制與調度的作用。

(5)ConfigurableApplicationContext:實現ApplicationContext,新增refresh()、close(),使ApplicationContext具備啟動、刷新、關閉等功能。



IoC容器的依賴注入

基於注解定義Bean

​ Spring2.0開始Spring提供基於注解的依賴注入功能。使用xml進行配置使Bean定義信息與Bean實現代碼分離,這就會造成代碼復雜且易錯。基於注解就可以在Bean實現類上進行注解標注,這大大降低的代碼的復雜性。

​ 定義Bean注解有以下4中:

​ (1)@Component:組件

​ (2)@Respository:對於Dao實現類進行標注

​ (3)@Service:對於Service實現類進行標注

​ (4)@Controller:對於Controller實現類進行標注

@Respository、@Service、@Controller是@Component的擴展,盡量使用3種特殊的注解,因為能夠標識出Bean的類型。

自動裝配

@Resource

​ resource是用J2EE提供的。

查找方式:

(1)按照指定name和type,容器中找到后對bean進行裝配,找不到拋出異常。

(2)按照指定name,容器中找到后對bean進行裝配,找不到拋出異常。

(3)按照指定type,容器中找到后對bean進行裝配,找不到或找到多個拋出異常。

(4)沒指定name和type,則先安裝name方式裝配,找不到這則按type進行裝配,都沒有拋異常。

@Autowired

​ autowired是spring提供的。

查找方式:

(1)按照類型查找,如果該類型bean不唯一則拋異常。

@Qualifier

查找方式:

(1)通過名稱指定Bean,同一個接口有多個實現,我們要裝配其中某一個Bean時,可以用qualifier通過名稱直接指定,一般結合Autowired一起使用。

基於Java類配置

@Bean

​ 普通的POJO可以通過標注@Configuration注解,就可以為Spring容器提供Bean定義信息,標注了@Bean的類方法就相當於提供了Bean的定義信息。當第三方庫引入時,可以使用@Bean注解將Bean交由Spring容器進行管理。

@Configuration
public class AppConfig {

    @Bean(name = "dataSource")
    public DataSource initDataSource() {
        return DataSourceBuilder.create().build();
    }
}

相當於

<beans>
    <bean id="dataSource" class="org.springframework.boot.jdbc.DataSourceBuilder"/>
</beans>



Bean的作用域

類型 說明
singleton IoC容器中僅存在一個Bean實例
prototype 每次調用都會返回新的Bean實例
request 每次Http請求都會創建一個Bean
session 同一個session共享Bean
globalSession 同一個全局Session共享一個Bean

singleton

singleton

prototype

prototype



FactoryBean

解釋說明

​ FactoryBean是能夠生產和修飾對象生成的工廠Bean。Spring提供了org.springframework.beans.factory. FactoryBean 接口,使用者能通過實現接口對Bean的實例化進行定制。

使用場景

(1)第三方框架提供的類,我們很難直接修改類代碼,為其添加@Service或@Componet時。
(2)當我們需要對第三方框架生成的實例進行修飾時。

應用案例

(1) mybatis-spring中org.mybatis.spring.SqlSessionFactoryBean



IoC容器內部關系

Spring容器、配置文件、Bean、應用程序關系圖

​ Bean配置信息配置了Bean的實現與依賴關系,容器將Bean配置信息注冊至注冊表中,然后根據注冊表加載與實例化,並建立Bean與Bean之間的依賴關系,最后將結果放置Bean緩存池中,供用應用程序調用。



JSR-250注釋

JSR-250注釋包括@PostConstruct,@PreDestroy,@Resource。@PostConstruct與@PreDestroy不用於依賴注入,用於標注對象生命周期的管理方法。

@Resource

​ @Resource與@Autowired的區別在上文已經講過就不再贅述。

@PostConstruct

如果想要在對象實例化后做一些准備工作,可以使用@PostConstruct。

    @Resource
    private ADRFingerprintBuilder adrFingerprintBuilder;

    @Resource
    private IOSFingerprintBuilder iosFingerprintBuilder;

    @Resource
    private List<ADRChecker> adrCheckers;

    @Resource
    private List<IOSChecker> iosCheckers;

    private static Map<String, EventTemplate> event = new HashMap<>();

    @PostConstruct
    public void buildEventMap() {
        event.put(ClientSourceEnum.ADR.getSource(), EventTemplate.builder().builder(adrFingerprintBuilder).checkers(adrCheckers).build());
        event.put(ClientSourceEnum.IOS.getSource(), EventTemplate.builder().builder(iosFingerprintBuilder).checkers(iosCheckers).build());
    }

​ 在完成實例化后,將實例放入map中,為后續操作做准備工作。

@PreDestroy

​ 在對象銷毀之前調用方法關閉資源或其他動作可以使用@PreDestroy。

@PreDestroy
   public void destroy(){
      System.out.println("destroy");
   }



解釋

  1. i18n:國際化信息也稱為本地化信息 。 Java 通過 java.util.Locale 類來表示本地化對象,它通過 “語言類型” 和 “國家/地區” 來創建一個確定的本地化對象。比如在發送一個具體的請求的時候,在header中設置一個鍵值對:"Accept-Language":"zh",通過Accept-Language對應值,服務器就可以決定使用哪一個區域的語言,找到相應的資源文件,格式化處理,然后返回給客戶端。



參考

[1]https://www.jianshu.com/p/6f0a59623090

[2]https://www.cnblogs.com/hujunzheng/p/11037577.html

[3]《精通Spring4.x企業應用開發實戰》

[4]《Spring揭秘》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM