Spring01——你應該瞭解的,有關 IOC 容器的一切

来源:https://www.cnblogs.com/weechang/archive/2020/03/25/12570922.html
-Advertisement-
Play Games

從本文開始,將開始介紹關於 Spring 的一些常見知識點。關註我的公眾號「Java面典」,每天 10:24 和你一起瞭解更多 Java 相關知識點。 在如今的 Java Web 開發中,Spring 生態圈占據著巨大的市場份額。幾乎是每個互聯網公司都在用 Spring 生態圈的東西。所以掌握Spr ...


從本文開始,將開始介紹關於 Spring 的一些常見知識點。關註我的公眾號「Java面典」,每天 10:24 和你一起瞭解更多 Java 相關知識點。

在如今的 Java Web 開發中,Spring 生態圈占據著巨大的市場份額。幾乎是每個互聯網公司都在用 Spring 生態圈的東西。所以掌握Spring 相關知識就成為了我們工作和麵試中必不可少的技能。今天將為各位帶來 Spring IOC 的相關知識。

概念

IOC —— Inversion of Control,即“控制反轉”,不是什麼技術,而是一種設計思想。指的是將設計好的對象交給容器控制,而不是傳統的在對象內部直接控制。

Spring 的 IOC 實現離不了DI(DI——Dependency Injection,即“依賴註入”。依賴註入指的是由容器動態的將某個依賴關係註入到組件之中)。

Spring 通過一個配置文件描述 Bean 及 Bean 之間的依賴關係,利用 Java 語言的反射功能實例化 Bean 並建立 Bean 之間的依賴關係。

IOC容器實現

IOC容器UML.png

IOC 容器主要由 BeanFactory 和 ApplicationContext 組成。BeanFactory 是 Spring 框架的基礎設施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的開發者,幾乎所有的應用場合我們都直接使用 ApplicationContext 而非底層的 BeanFactory。

BeanFactory

BeanFactory 是 Spring 框架的基礎設施,面向 Spring 本身,BeanFactory 主要有以下組件:

  • BeanDefinitionRegistry:註冊表,提供了向容器手工註冊 BeanDefinition 對象的方法。Spring 配置文件中每一個節點元素在 Spring 容器里都通過一個 BeanDefinition 對象表示,它描述了 Bean 的配置信息;

  • BeanFactory:頂層介面。它最主要的方法就是 getBean(String beanName),該方法從容器中返回特定名稱的 Bean;

  • ListableBeanFactory:該介面定義了訪問容器中 Bean 基本信息的若幹方法,如查看 Bean 的個數、獲取某一類型 Bean 的配置名、查看容器中是否包括某一 Bean 等方法;

  • HierarchicalBeanFactory:父子級聯 IOC 容器的介面,子容器可以通過介面方法訪問父容器; 通過HierarchicalBeanFactory 介面, Spring 的 IOC 容器可以建立父子層級關聯的容器體系,子容器可以訪問父容器中的 Bean,但父容器不能訪問子容器的 Bean。Spring 使用父子容器實現了很多功能,比如在 Spring MVC 中,展現層 Bean 位於一個子容器中,而業務層和持久層的 Bean 位於父容器中。這樣,展現層 Bean 就可以引用業務層和持久層的 Bean,而業務層和持久層的 Bean 則看不到展現層的 Bean;

  • ConfigurableBeanFactory:定義了設置類裝載器、屬性編輯器、容器初始化後置處理器等方法,增強了 IOC 容器的可定製性;

  • AutowireCapableBeanFactory:定義了將容器中的 Bean 按某種規則(如按名字匹配、按類型匹配等)進行自動裝配的方法;

  • SingletonBeanRegistry:定義了允許在運行期間向容器註冊單實例 Bean 的方法;對於單實例( singleton)的 Bean 來說,BeanFactory 會緩存 Bean 實例,所以第二次使用 getBean() 獲取 Bean 時將直接從IOC 容器的緩存中獲取 Bean 實例。Spring 在 DefaultSingletonBeanRegistry 類中提供了一個用於緩存單實例 Bean 的緩存器,它是一個用 HashMap 實現的緩存器,單實例的 Bean 以 beanName 為鍵保存在這個 HashMap 中。

  • 依賴日誌框架:在初始化 BeanFactory 時,必須為其提供一種日誌框架,比如使用 Log4J, 即在類路徑下提供 Log4J 配置文件,這樣啟動 Spring 容器才不會報錯。

ApplicationContext 面向開發應用

ApplicationContext 由 BeanFactory 派 生 而 來 , 提 供 了 更 多 面 向 實 際 應 用 的 功 能 。ApplicationContext 繼承了 HierarchicalBeanFactory 和 ListableBeanFactory 介面,在此基礎上,還通過多個其他的介面擴展了 BeanFactory 的功能:

  • ClassPathXmlApplicationContext:預設從類路徑載入配置文件;
  • FileSystemXmlApplicationContext:預設從文件系統中裝載配置文件;
  • ApplicationEventPublisher:讓容器擁有發佈應用上下文事件的功能,包括容器啟動事件、關閉事件等;
  • MessageSource:為應用提供 i18n 國際化消息訪問的功能;
  • ResourcePatternResolver: 所 有 ApplicationContext 實現類都實現了類似於 PathMatchingResourcePatternResolver 的功能,可以通過帶首碼的 Ant 風格的資源文件路徑裝載 Spring 的配置文件;
  • LifeCycle:該介面是 Spring 2.0 加入的,該介面提供了 start()和 stop()兩個方法,主要用於控制非同步處理過程。在具體使用時,該介面同時被 ApplicationContext 實現及具體Bean 實現, ApplicationContext 會將 start/stop 的信息傳遞給容器中所有實現了該介面的 Bean,以達到管理和控制 JMX、任務調度等目的;
  • ConfigurableApplicationContext:擴展於 ApplicationContext,它新增加了兩個主要的方法: refresh()和 close(),讓 ApplicationContext 具有啟動、刷新和關閉應用上下文的能力。在應用上下文關閉的情況下調用 refresh()即可啟動應用上下文,在已經啟動的狀態下,調用 refresh()則清除緩存並重新裝載配置信息,而調用 close()則可關閉應用上下文。

WebApplicationContext

WebApplicationContext 是專門為 Web 應用準備的,它允許從相對於 Web 根目錄的路徑中裝載配置文件完成初始化工作。從 WebApplicationContext 中可以獲得ServletContext 的引用,整個 Web 應用上下文對象將作為屬性放置到 ServletContext 中,以便 Web 應用環境可以訪問 Spring 應用上下文。

四種依賴註入方式

構造器註入

/*帶參數,方便利用構造器進行註入*/
public CatDaoImpl(String message){ 
    this. message = message; 
} 

<bean id="CatDaoImpl" class="com.CatDaoImpl"> 
    <constructor-arg value=" message "></constructor-arg> 
</bean>

setter 方法註入

private int id; 
public int getId() { return id; } 
public void setId(int id) { this.id = id; } 

<bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>

靜態工廠註入

靜態工廠顧名思義,就是通過調用靜態工廠的方法來獲取自己需要的對象,為了讓 Spring 管理所有對象,我們不能直接通過"工程類.靜態方法()"來獲取對象,而是依然通過 Spring 註入的形式獲取:

public class DaoFactory { 
    //靜態工廠 
    public static final FactoryDao getStaticFactoryDaoImpl(){ 
        return new StaticFacotryDaoImpl(); 
    } 
} 

public class SpringAction { 

    //註入對象
    private FactoryDao staticFactoryDao; 
    //註入對象的 set 方法 
    public void setStaticFactoryDao(FactoryDao staticFactoryDao) { 
        this.staticFactoryDao = staticFactoryDao; 
    } 
} 

<bean name="springAction" class=" SpringAction" > 
    <!--使用靜態工廠的方法註入對象,對應下麵的配置文件--> 
    <property name="staticFactoryDao" ref="staticFactoryDao"></property> 
 </bean> 
 
<!--此處獲取對象的方式是從工廠類中獲取靜態方法--> 
<bean name="staticFactoryDao" class="DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

實例工廠

實例工廠的意思是獲取對象實例的方法不是靜態的,所以你需要首先 new 工廠類,再調用普通的實例方法:

public class DaoFactory { 
    //實例工廠 
    public FactoryDao getFactoryDaoImpl(){ 
        return new FactoryDaoImpl();
    } 
} 

public class SpringAction { 
    private FactoryDao factoryDao;
    //註入對象 
    public void setFactoryDao(FactoryDao factoryDao) { 
        this.factoryDao = factoryDao; 
    } 
} 

<bean name="springAction" class="SpringAction"> 
    <!--使用實例工廠的方法註入對象,對應下麵的配置文件--> 
    <property name="factoryDao" ref="factoryDao"></property> 
</bean> 

 <!--此處獲取對象的方式是從工廠類中獲取實例方法--> 
<bean name="daoFactory" class="com.DaoFactory"></bean> 
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>

五種不同方式的自動裝配

Spring 裝配包括手動裝配和自動裝配,手動裝配是有基於 xml 裝配、構造方法、setter 方法等;自動裝配有五種方式,可以用來指導 Spring 容器用自動裝配方式來進行依賴註入:

  1. no:預設的方式是不進行自動裝配,通過顯式設置 ref 屬性來進行裝配;
  2. byName:通過參數名 自動裝配,Spring 容器在配置文件中發現 bean 的 autowire 屬性被設置成 byname,之後容器試圖匹配、裝配和該 bean 的屬性具有相同名字的 bean;
  3. byType:通過參數類型自動裝配,Spring 容器在配置文件中發現 bean 的 autowire 屬性被設置成 byType,之後容器試圖匹配、裝配和該 bean 的屬性具有相同類型的 bean;
    註意:使用 byType 首先需要保證同一類型的對象,在 Spring 容器中唯一,若不唯一會報不唯一的異常。
  4. constructor:這個方式類似於 byType, 但是要提供給構造器參數,如果沒有確定的帶參數的構造器參數類型,將會拋出異常;
  5. autodetect:首先嘗試使用 constructor 來自動裝配,如果無法工作,則使用 byType 方式。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 在執行python程式時遇到 ‘ModuleNotFoundError: No module named 'xxxxx'’ : 例如: 圖片中以導入第三方的 'requests' 模塊為例,此報錯提示找不到requests模塊。在python中,有的 模塊是內置的(直接導入就能使用)有的模塊是 ...
  • 近期在開發過程中,因為項目開發環境連接的mysql資料庫是阿裡雲的資料庫,而阿裡雲的資料庫版本是5.6的。而測試環境的mysql是自己安裝的5.7。因此在開發過程中有小伙伴不註意寫了有關group by的sql語句。在開發環境中運行是正常的,而到了測試環境中就發現了異常。 原因分析:MySQL5.7 ...
  • 隨著分散式技術的普及和海量數據的增長,io的能力越來越重要,java提供的io模塊提供了足夠的擴展性來適應。 我是李福春,我在準備面試,今天的問題是: java中的io有哪幾種? java中的io分3類: 1,BIO ,即同步阻塞IO,對應java.io包提供的工具;基於流模型,雖然直觀,代碼實現也 ...
  • 1. 概念 Reactive 非常適合低延遲、高吞吐量的工作負載。 Reactive Processing 是一種範式(規範),它使開發人員能夠構建非阻塞的、非同步的應用程式,這些應用程式能夠處理背壓(流控制) Reactive Streams 為無阻塞背壓的非同步流處理提供標準。 Reactor 是基 ...
  • 多態(Polymorphism)按字面的意思就是“多種狀態”。在面向對象語言中,介面的多種不同的實現方式即為多態。引用Charlie Calverts對多態的描述——多態性是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作 ...
  • string 字元串在所有的語言中都非常重要,c++也不例外,接下來我們將介紹string中的常用方法 1. size() 和 length() 函數 : 他們返回字元串的真實長度,且不會因為空格而截斷,這兩個方法完全等價,使用及輸出如下: #include<iostream> #include<s ...
  • | 好看請贊,養成習慣 你有一個思想,我有一個思想,我們交換後,一個人就有兩個思想 If you can NOT explain it simply, you do NOT understand it well enough 現陸續將Demo代碼和技術文章整理在一起 "Github實踐精選" ,方便 ...
  • 一、語法 作用:簡化函數代碼 格式:lambda 參數列表 :表達式 P.s: lambda表達式參數可有可無,參數寫法同函數 lambda函數能接收任何數量的參數但只能返回一個表達式的值 def func0(): return 100 func = lambda: 100 # lambda本質是一 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...