一,容器相關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建立過程: