spring Ioc和DI相關

一,容器相關spring

Ioc(控制反轉)的核心是DI(依賴注入),爲了提供一種簡單的方式設置組件依賴項(對象協做者),並在整個生命週期中管理這些依賴項。緩存

概念:mybatis

1.依賴對象:須要弄些依賴對象的組件,或者叫目標對象。app

控制反轉的類型:函數

1.依賴注入:優先使用spa

(1)構造函數注入:在構造函數中設置須要的依賴項,也就是帶參數的構造函數。若是沒有依賴項沒法建立對象。prototype

注意一下如何選擇構造函數就能夠,好比能夠指定參數類型。線程

(2)setter依賴注入:提供專門的setter方法設置依賴項。能夠在沒有依賴項的時候建立對象,而後經過setter方法設置依賴項。代理

@Autowired能夠註釋在方法(包括構造函數)上,容器會自動給參數設置依賴,根據參數名稱。xml

(3)字段注入

@Autowried

private Inspiration inspirationBean;  最經常使用方式。

@value註解能夠給方法參數設置初始值。

(4)查找方法注入

動態獲取依賴項,能夠解決單例引用非單例的狀況。使用CGLIB動態代理實現。

原理:核心是使用<lookup-method>或者@Lookup,以註解方法爲例。首先使用@Scope("prototype")改變依賴項的做用域爲非單例,而後在目標bean中設置一個返回空的方法,並使用@Lookup註釋

這樣在調用這個方法的時候spring就會動態的去獲取依賴項。注意容器中的bean默認都是單例模式。

(5)方法替換

動態的替換bean上的任意方法,而無需改變源代碼。使用CGLIB動態代理實現。

原理:核心是使用<replaced-method name='被替換方法名稱' replacer='替換bean'>,其中replacer是實現了MethodReplacer接口的類,並註冊爲bean。

相關說明:

   a.若是組件建立以前必須其餘組件先建立就使用構造函數注入,其餘的通常使用setter注入。

   b.注意組件和配置的區別,接口中通常會這種不少配置方法,而不會提供依賴項。

public interface NewsletterSender(){

      void setSmtpServer(String smtpServer);

      String getSmtpServer();

      void setFromAddress(String fromAddress);

      String getFromAddress();

      void send();

}

上面接口前四個都是配置方法,爲最後一個方法提供配置,通常放到接口中能夠定義出改接口的業務邏輯。可是,不要把特定的組件放到接口中,放到子類中進行聲明設置。

組件和配置的區別:

(1)配置參數是被動的,通常是由其餘函數調用。

(2)配置參數一般是信息,而不是組件

(3)配置參數一般是簡單值或者簡單值的集合。

c.setter注入能夠在不建立父組件的狀況下修改依賴項

2.依賴查找:

(1)依賴拉取:從JNDI註冊表中拉取Bean,容器中的bean都在某個註冊表中註冊,獲取依賴項的時候從註冊表中查找。

(2)上下文依賴查找:直接從容器中獲取,而不是從註冊表中。組件都實現特定接口,該接口有一個特定方法能夠獲取到當前組件。

二:spring中的應用

1.依賴注入的核心BeanFactory接口,bean是組件。BeadFacotry管理bean的整個生命週期。

2.應用程序必須建立一個實現了BeanFactory接口的實例(經常使用的是ApplicationContext,須要實現BeanDefinitionReader接口,才能從配置中獲取bean配置信息),並使用bean和依賴信息進行配置(bean配置由實現了BeanDefinition接口的實例表示,bean配置不只存儲bean自己信息還有它依賴的bean的信息,一般配置信息放到外部,好比xml或者property中分別對應不一樣的類進行加載)。

示例:

(1)

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();//建立beanfactory

XmlBeanDefinitionReadder rdr = XmlBeanDefinitionReader(factory);//建立bean配置加載類

rdr.loanBeanDefinitions(new ClassPathResource('spring/xml-bean-factory-config.xml'));//加載bean配置。

 (2)GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

ctx.load('spring/xml-bean-factory-config.xml');//跟上面相比省掉了第二步。

3.使用Java配置

當應用第三方庫,好比mybatis,的時候一般須要建立不少固定的bean,通常這些都不會在改變,這種狀況可使用Java配置。

配置類使用@Configuration註解,幷包含@Bean註解的方法,這些方法由Spring Ioc 容器直接調用來實例化bean。bean名稱與用於建立它的方法的名稱相同

獲取配置類中的bean須要使用

ApplicationContext ctx = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);

獲取bean配置還有其餘方式:@ComponentScan(basePackages={"com.apress.prospring5.ch3.annotation"})  @ImportResource(locations = {"classpath:spring/app-context-xml.xml"});

4.經過使用SpEL,Spring能夠訪問任何Spring管理的bean和屬性

@Value("#{bean.property}")
5.ApplicationContext能夠嵌套,也就是能夠聲明多個容器,並設置父子關係。並能相互使用對方容器中的bean。

6.@Autowired 若是設置的是一個集合類型對象,Spring會嘗試將當前ApplicationContext中全部該類型的對象都注入進來,可能會致使意外的依賴項被注入。而若是沒有改類型的bean,會拋出異常。

正確方式:

(1)@Resource(name="map")

(2)@Autowired

       @Qualifier("map")

上面的兩種方式能夠明確注入的bean名稱,避免注入其餘的依賴項。

7. bean做用域

(1)單例做用域

(2)原型做用域

(3)請求做用域:針對每一個HTTP請求實例化一個bean

(4)會話做用域:針對每一個HTTP會話(可能有多個請求)實例化一個bean

(5)全局會話做用域:應用程序的全部Portlet之間共享。

(6)線程做用域:每一個線程實例化一個bean

(7)自定義做用域:實現org.springframwork.beans.factory.config.Scope接口

 8.bean依賴順序設置

若是在配置中沒有體現一個bean使用其餘的bean,而是在代碼中須要調用,那麼spring會沒法感知到,從而有可能形成bean沒法被調用。針對這個使用註解@DependsOn("bean名稱");

9.自動裝配模式

(1)byName模式:根據名稱進行注入

(2)byType模式:根據類型進行注入

(3)構造函數模式:跟byType功能上相同,都是根據類型,只是使用構造函數而不是setter來執行注入。並且匹配的是參數最多的構造函數。

(4)默認模式:自動在構造函數和byType模式之間選擇。

說明:

(1)自動裝配必須保證bean是惟一的,不然會報org.springframework.beans.factory.NoSuchBeanDefinitionException異常。

(2)若是確實有多個相同的類型bean的時候,可使用@Qualifier("bean名稱")來指定具體的bean。一般這個註解跟在@Autowired後面。

  

核心問題:

1.如何解決循環依賴。

bean建立過程:

(1)createBeanInstance:實例化,其實也就是調用對象的 構造方法實例化對象
(2)populateBean:填充屬性,這一步主要是多bean的依賴屬性進行填充
(3)initializeBean:調用spring xml中的init 方法。
三級緩存: 
singletonFactories : 單例對象工廠的cache 
earlySingletonObjects :提早暴光的單例對象的Cache 
singletonObjects:單例對象的cache
 
原理:緩存的使用是從下到上一次查找,若是在singletonObjects中找不到(說明尚未建立),而後就去earlySingletonObjects中去查找,若是仍是找不到就到singletonFactories中查找(這個緩存存放的是createBeanInstance建立出來的對象,其中屬性爲空和init方法未調用,能夠理解爲一個空殼,可是bean已經有了,而且能夠區分出來),這裏面必定會獲取到,而後從這個緩存中刪除,放到earlySingletonObjects中去。
 
注意:spring只能解決屬性循環依賴,沒法解決構造函數循環依賴
相關文章
相關標籤/搜索