Spring中的IoC容器

什麼是IoC

什麼是耦合和內聚

  • 耦合指的就是模塊之間的依賴關係。模塊間的依賴越多,則表示耦合度越高,相應的維護成本就越高。
  • 內聚指的是模塊內功能之間的聯繫。模塊內功能的聯繫越緊密,則表示內聚度越高,模塊的職責也就越單一。

因此在程序開發中應該儘可能的下降耦合,提升內聚。也就是設計原則中的開閉原則和單一職責原則。java

工廠模式

工廠模式就是用來解決程序間耦合的一種設計模式。能夠把全部要建立的對象放在工廠的一個集合裏,當須要使用這個對象的時候,直接從工廠裏面取出來用就行。
工廠模式的優勢:spring

  • 一個調用者想建立一個對象,只須要指定相應的名字便可從工廠中得到這個對象。
  • 屏蔽了產品的具體實現,調用者只關心產品的接口。

控制反轉(IoC)

控制反轉在維基百科中的定義:數據庫

控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,能夠用來減低計算機代碼之間的耦合度。其中最多見的方式叫作依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用傳遞(注入)給它。編程

下面再從控制和反轉兩個詞分兩個方面來理解:設計模式

  • 誰控制誰?IoC容器控制了對象。控制什麼?控制了對象要獲取的外部資源(其它對象或數據等)
  • 什麼是反轉?是IoC容器查找並注入依賴給對象,對象是被動的接受,而不是主動的建立,因此是反轉。

經過new方式來主動獲取對象:
springboot

image.png

經過IoC容器獲取對象(注意看箭頭的方向,是否是反轉了):
bash

\[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-McaurwWV-1576318447166)(https://i.loli.net/2019/12/14/U1o3cR6mps4kQvH.png)\]

有了IoC容器後,把建立和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,因此對象與對象之間是鬆散耦合,這樣也方便測試,利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活。session

依賴注入(DI)

依賴注入在維基百科中的定義函數

在軟件工程中,依賴注入是種實現控制反轉用於解決依賴性設計模式。一個依賴關係指的是可被利用的一種對象(即服務提供端) 。依賴注入是將所依賴的傳遞給將使用的從屬對象(即客戶端)。該服務是將會變成客戶端的狀態的一部分。 傳遞服務給客戶端,而非容許客戶端來創建或尋找服務,是本設計模式的基本要求。測試

其實依賴注入和控制反轉表達的是一個意思。控制反轉是一種思想,而依賴注入是這個思想的最典型的實現方法。
由IoC來控制對象的依賴,經過構造函數、變量或Setter等方法來將依賴注入到對象中,這樣就將對象和對象的依賴進行了解耦。

spring中的工廠類

咱們經常使用的spring容器是ApplicationContext,先來看一下它的依賴結構。

\[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Y7hwa6zl-1576318447168)(https://i.loli.net/2019/12/14/5X8F4lUgvemJMTc.png)\]
由圖可知,spring容器中的頂層接口是BeanFactory。ApplicationContext是它的子接口(注意這個也是個接口哦)。它默認一讀取配置文件,就會建立對象放到容器中。
再來看一下ApplicationContext的三個主要的實現類。
\[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-R9nohp4k-1576318447169)(https://i.loli.net/2019/12/14/hsiDTJt4YxOHWn8.png)\]

  • ClassPathXmlApplication:它是從類的根路徑下加載xml配置文件(推薦用這種)。
  • FileSystemXmlApplication: 它是從磁盤路徑上加載配置文件,配置文件能夠在磁盤的任意位置。(但使用不靈活,不推薦)
  • AnnotationConfigApplication:當咱們使用註解配置容器對象時,須要使用此類來建立spring容器。它用來讀取註解。(springboot默認使用這個)

Bean的建立和管理

bean標籤

做用 : 用於配置對象讓spring來建立的。默認狀況下它調用的是類中的無參構造函數。若是沒有無參構造函數則不能建立成功。
屬性

  • id:給對象在容器中提供一一個惟一 標識。用於獲取對象。
  • class:指定類的全限定類名。用於反射建立對象。默認狀況下調用無參構造函數。
  • scope:指定對象的做用範圍。
    • singleton : 單例對象,也是默認的。
    • prototype : 多例對象,每次都建立一個不一樣的對象。
    • request :WEB 項目中,Spring建立一個Bean的對象,將對象存入到request域中.
    • session : WEB項目中,Spring建立一個Bean的對象,將對象存入到session域中。
    • global session:WEB項目中,應用在集羣環境.若是沒有集羣環境那麼globalSession至關於session.
  • init-method:指定類中的初始化方法名稱。
  • destroy-method:指定類中銷燬方法名稱。

bean的做用範圍和生命週期

  1. 單例對象: scope="singleton" 一個應用只有一一個對象的實例。它的做用範圍就是整個引用。 生命週期:
  • 對象出生:當應用加載,建立容器時,對象就被建立了。
  • 對象活着:只要容器在,對象-直活着。
  • 對象死亡:當應用卸載,銷燬容器時,對象就被銷燬了。
  1. 多例對象: scope="prototype" 每次訪問對象時,都會從新建立對象實例。 生命週期:
  • 每次訪問對象時,都會從新建立對象實例。
  • 對象活着:只要對象在使用中,就一直活着。
  • 對象死亡:由java的垃圾回收器機制來處理。

spring中的註解

用於建立對象的

至關於<bean id = "" class = "" />
複製代碼

1 、@component
做用:把資源讓spring來管理,至關於在xml中註冊一個bean。
屬性:value:指定bean的id.若是不指定value屬性,默認bean的id是當前類的類名。首字母小寫。 二、 @Service 、@Repository 、@Controller 他們都是對@Component註解的衍生,其實做用是如出一轍的,只是提供了更明確的語義化。

  • @Repository:通常用於持久層的註解。
  • @Service:通常用於業務層的註解
  • @Controller:通常用於表現層的註解。

用於注入數據的

至關於<property name = "" ref = "" />  或
      <property name= "" value = "" />
複製代碼

@Autowried

做用:自動按照類型注入。當使用註解注入屬性時,set 方法能夠省略。它只能注入其餘bean類型(ByType)。當有多個類型匹配時,使用要注入的對象變量名稱做爲bean的id (ByName) ,在spring容器查找,找到了也能夠注入成功。找不到就報錯。
三種注入方式(屬性輸入、Setter注入、構造函數注入):

/** * 使用變量注入依賴 */
@Autowired
private IAccountDao accountDao ;

/** * 使用構造器注入 spring推薦使用這個 * @param accountDao 要注入的依賴 */
@Autowired
public AccountServiceImpl(IAccountDao accountDao) {
    this.accountDao = accountDao;
}

/** * 使用Setter注入 * @param accountDao 要注入的依賴 */
@Autowired
public void setAccountDao(IAccountDao accountDao) {
    this.accountDao = accountDao;
}
複製代碼

@Qualifier

做用:在自動按照類型注入的基礎之上,再按照Bean的id注入。它在給字段注入時不能獨立使用,必須和@Autowire一塊兒使用;可是給方法參數注入時,能夠獨立使用。
屬性:value:指定bean的id.

@Resource

做用:@Resource採用 name 屬性。默認狀況下,Spring 將 value 解釋爲要注入的 bean name。也就是ByName注入。
屬性:value:指定bean的id.

@Value

做用:用於注入基本類型數據和String類型數據
屬性:用於指定值,可以使用SpEL表達式。

用於改變做用域的

至關於<bean id = "" class = "" scope = ""/>中的scope屬性
複製代碼

@Scope

做用:指定bean的做用範圍。
屬性:value:指定bean的做用範圍。取值: singleton prototype request session globalsession。

生命週期相關的

至關於<bean id = "" class = "" init-method = "" destory-method = ""/>中的init-method屬性和destory-method屬性
複製代碼

@PostConstruct

做用:用於指定初始化方法

@PostDestory

做用:用於指定銷燬方法

spring中的新註解

@Configuration

做用:用於指定當前類是一個spring配置類,當建立容器時會從該類上加載註解。獲取容器時須要使用AnnotationApplicationContext (有@Configuration註解的類. class)。
屬性:value:用於指定配置類的字節碼

@ComponentScan

做用:用於指定spring在初始化容器時要掃描的包。做用和在spring的xml配置文件中的<context : component-scan base-package="com. itheima"/>是同樣的。
屬性:basePackages: 用於指定要掃描的包。和該註解中的value屬性做用同樣。

Bean

做用:該註解只能寫在方法(該方法的返回值做爲bean放到容器中)上,代表使用此方法建立一個對象, 而且放入spring容器。
屬性:name:給當前@Bean註解方法建立的對象指定一個名稱 (即bean的id)。

@PropertySource

做用:用於加載.properties文件中的配置。例如咱們配置數據源時,能夠把鏈接數據庫的信息寫到properties配置文件中,就可使用此註解指定properties配置文件的位置。
屬性:value[] :用於指定properties文件位置。若是是在類路徑下,須要寫上classpath:。
示例:

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig{
}
複製代碼

@Import

做用:用於導入其餘配置類,在引入其餘配置類時,能夠不用再寫@Configuration註解。固然,寫上也沒問題。
屬性:value[] :用幹指定其餘配置類的字節碼。
示例:

@Configuration
@ComponentScan(basePackages = "com.ncusoft.springDemos")
@Import({ JdbcConfig.class })
public class SpringConfiguration {
}
複製代碼

選擇XML仍是註解?

先來看一下各自的優點:

  • 註解的優點:配置簡單,維護方便(咱們找到類,就至關於找到了對應的配置)。
  • XML的優點:修改時,不用改源碼。不涉及從新編譯和部署。

應該根據實際的開發來選擇使用(springboot推薦使用註解),通常在source code(源代碼)中的類使用註解來建立bean(更方便,只需一個註解搞定)。從外部引入的依賴可選擇使用XML來建立bean。

相關文章
相關標籤/搜索