- java垃圾回收機制幫助咱們實現了這個過程;
- 而ioc則是讓咱們無需考慮對象的建立過程,由ioc容器幫咱們實現對象的建立、注入等過程。
【說明】:java
Contextweb
- 對於IoC和DI的理解
- BeanFactory
- ApplicationContext
Bean數據庫
- SpEL(#)
- 引入外部的屬性文件($)
基於XML的Bean配置編程
配置Bean設計模式
- 經過全類名
- 經過工廠方法
- 經過 FactoryBean
裝配Bean的屬性安全
- 經過屬性
- 經過構造器
基於註解的Bean配置架構
裝配Bean的屬性app
- Autowired等註解
配置Bean框架
- Context:componentScan節點
圖片描述
【說明】:工具
IoC 概念
- 應用控制反轉,對象在建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用,傳遞給它。也能夠說,依賴注入到對象中。因此,控制反轉是,關於一個對象如何獲取他所依賴的對象的引用,這個責任的反轉。
- 控制反轉(Inversion of Controll)是一個重要的面向對象編程的法則,來削弱計算機程序的耦合問題,也是輕量級 Spring 框架的核心。
- 控制反轉通常分爲兩種類型,依賴注入(Dependency Injection,DI)和依賴查找(Dependency Lookup),依賴注入應用普遍。
深刻分析
- 依賴於誰?應用程序依賴於 IoC 容器
- 爲何要依賴?應用程序須要 IoC 容器來提供對象須要的外部資源
- 誰注入誰?IoC容器注入應用程序某個對象,應用程序依賴的對象
- 注入了社麼?注入某個對象所須要的外部資源(包括對象、資源、常量對象)
與new對象的區別
- 正轉與反轉,傳統應用程序是由咱們將本身在對象中主動控制去直接獲取依賴對象,也就是正轉;而反轉則是由容器來幫助建立及注入依賴對象。
IoC優缺點
- 優勢:實現組件之間的解耦,提供程序的靈活性和可維護性
- 缺點:對象生成由於是使用反射編程,在效率上有損耗
2、Spring IoC 容器
【Spring核心組件】:它們構建起了整個Spring的骨骼架構,沒有它們就不可能有AOP、Web等特性功能。
- Core
- Context
- Bean
Spring解決了一個很是關鍵的問題,它可讓你對對象之間的關係轉而用配置文件來管理,或者註解,也就是它的依賴注入機制。而這個注入關係在一個叫Ioc的容器中管理。Ioc容器就是被Bean包裹的對象。Spring正是經過把對象包裝在Bean中從而達到管理這些對象及作一些列額外操做的目的。
- 概念:
在每一個框架中都有一個容器的概念,所謂的容器就是將經常使用的服務封裝起來,而後,用戶只須要遵循必定的規則,就能夠達到統1、靈活、安全、方便、快速的目的
具備依賴注入功能的容器,負責實例化、定位、配置應用程序中的對象及創建這些對象間的依賴
- Bean的概念:
由IoC容器管理的那些組成應用程序的對象就叫Bean
Bean就是由Spring容器初始化、裝配及管理的對象,除此以外,Bean就與應用程序中的其餘對象沒什麼區別了
- 元數據 BeanDefinition
肯定如何實例化Bean、管理Bean之間的依賴關係及管理Bean,就須要配置元數據,在Spring中由BeanDefintion表明
如何工做(以XML配置方式解釋)
- 準備配置文件:配置文件中聲明 Bean 定義也就是 Bean 配置元數據。
- 由 IoC 容器進行解析元數據:IoC 容器的 Bean Reader 讀取並解析配置文件,根據定義生成 BeanDefintion 配置元數據對象,IoC 容器根據 BeanDefintion 進行實例化、配置及組裝 Bean。
- 實例化 IoC 容器:由客戶端實例化容器,獲取須要的 Bean。
- hello world
@Test public void testHelloWorld() { // 一、讀取配置文件實例化一個 IoC 容器 ApplicationContext context = new ClassPathXmlApplicationContext("helloWorld.xml"); // 二、從容器獲取 Bean,主次此處徹底「面向接口編程」 HelloApi helloApi = context.getBean("hello", HelloApi.class); // 三、執行業務邏輯 helloApi.sayHello(); }
三、Spring IoC 容器工做原理
- Bean : 【演員】Spring 的 bean 實例
- Context :【導演】Spring 的上下文
Bean 包裝的是 Object,而 Object 必然有數據,如何給這些數據體提供生存環境就是 Context 要解決的問題,對 Context 來講就是要發現每一個 Bean 之間的關係,爲它們創建這種關係並維護關係,因此 Context 就是 Bean 關係的集合,這個關係機構叫作 IoC 容器。
- Core :【道具】Spring 的核心工具包
創建和維護每一個 Bean 之間的關係所須要的一些核心工具包。至關於 Util。
IoC 中最核心的接口是 BeanFactory 提供 IoC 的高級服務,而 ApplicationContext 是創建在 BeanFactory 基礎之上提供抽象的面向應用的服務。
- BeanFactory
提供了一種先進的配置機制來管理任何種類 Bean 對象,這種配置機制考慮到任何一種可能的存儲方式。
- ApplicationContext
創建在 BeanFactory,具備 BeanFactory 的全部功能和行爲
- MessageSource,提供國際化的消息服務,擴展類 MessageResource 接口
- 資源訪問,如 URL 和文件
- 事件傳播
- 載入多個(有繼承關係)上下文,使得每個上下文都專一於一個特定的層次,好比應用的 web 層。
不一樣點
選用哪一個?
- BeanFactory:是延遲加載,若是 Bean 的某一個屬性沒有注入,BeanFactory 加載後,直至第一次使用調用 getBean 方法纔會拋出異常
- ApplicationContext:則在初始化自身時檢驗,這樣有利於檢查所依賴屬性是否注入;因此一般狀況下使用 ApplicationContext。
特性表 BeanFatory / ApplicationContext
* Bean 實例化/裝配 YES YES * 啓動 BeanPostProcessor註冊 NO YES * 啓動 BeanFactoryPostProcessor註冊 NO YES * 便捷的 MessageSource反問(i18n) NO YES * ApplicationEvent 發送 NO YES
關係
* BeanFactory 提供了配置框架和基本的功能 * ApplicationContext 創建在 BeanFactory 之上,並增長了其餘功能 * 通常來講,ApplicationContext 是 BeanFactory 的徹底超集,任何 BeanFactory 功能和行爲的描述也一樣被認爲適用於 ApplicationContext。
在Spring框架中,依賴注入(DI)的設計模式是用來定義對象彼此間的依賴。使用xml配置bean的狀況下,它主要有兩種類型:
- Setter 方法注入
- 構造器注入
- 註解 @autowired
固然,有了註解以後,使用註解的方式更加方便快捷。即自動裝配功能實現屬性自動注入(@autowire)。
當運行 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
構造方法 ClassPathXmlApplicationContext(String configLocation), 調用了 this(new String[] {configLocation}, true, null); 該構造方法具體代碼:
【ClassPathXmlApplicationContext構造方法】:
/** * 在 parent 下建立 ClassPathXmlApplicationContext, * 從 XML 中讀取素有 Bean 定義。 * @param configLocations 配置文件路徑如 c:\simpleContext.xml * @param refresh 是否須要自動刷新 context,refrest--> 從新加載 * 加載全部的 bean 定義,建立全部單例。 * refresh 爲 true 的時候,根據 context 來手工刷新 * @param parent the parent context * @throws BeansException if context creation failed * @see #refresh() */ public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException{ // 初始化XmlApplicationContext super(parent); // 轉換配置文件的路徑 setConfigLocations(configLocations); if(refresh) { // 從新刷新全部的 context,這一篇的重點 refresh(); } }
【refresh方法】:
/** * 加載或刷新持久的配置,多是xml文件,properties文件,或者關係型數據庫的概要。 * 做爲一啓動方法,若是初始化失敗將會銷燬已經建立好的單例,避免重複加載配置文件。 * 換句話說,在執行這個方法以後,要不所有加載單例,要不都不加載。 public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { // 初始化配置準備刷新,驗證環境中的一些必選參數 prepareRefresh(); // 告訴繼承銷燬內部的 factory建立新的 factory 實例 // 初始化 Bean 實例 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 初始化 beanFactory 的基本信息,包括 classLoader、environment、忽略的註解等。 prepareBeanFactory(beanFactory); try { // beanFactory 內部的 postProces,能夠理解爲 context 中的 PostProcess 的補充 beanFactory.postProcessBeanFactory(beanFactory)p; // 執行 BeanFactoryPostProcessor(在beanFactory)初始化過程當中,bean 初始化以前,修改BeanFactory 參數 // BeanDefinitionRegistryPostProcessor 其實也是繼承自 BeanFactoryPostProcessor, // 多個對 BeanDefinitionRegistry 的支持 invokeBeanFactoryPostProcessors(beanFactory) // 執行 postProcess,那 BeanPoseProcessor 是什麼呢,是爲了在 bean 加載過程當中修改 bean 的內容, // 使用Before、After分別對應初始化前和初始化後 registerBeanPostProcessors(beanFactory); // 初始化 MessageSource,主要用於 I18N 本地化的內容 initMessageSource(); // 初始化事件廣播 ApplicationEventMulticaster,使用觀察者模式,對註冊的 ApplicationEvent 時間進行捕捉 initApplicationEventMulticaster(); // 初始化特殊的 bean 方法 onRefresh(); // 將全部 ApplicationEventListener 註冊到 ApplicationEventMulticaster 中 registerListeners(); // 初始化全部部位 lazy-init 的bean,singleton 實例 finishBeanFactoryInitialization(beanFactory); // 初始化 lifeCycle 的bean啓動(例如 quartz 的定時器),若是開啓 JMX 則將 ApplicationContext 註冊到上面 finishRefresh(); } catch(BeansException ex) { // 銷燬已經建立單例 resources.destroyBeans(); // 將 context 的狀態轉換爲無效,標示初始化失敗 flag.cancelRefresh(ex); } } }
【容器初始化時序圖】: