javascript
factorybean 代理类不能按照类型注入_《Spring入门经典》:使用Spring进行依赖注入
第二章:使用Spring進(jìn)行依賴注入
重點(diǎn):配置并使用Spring容器
使用不同類型的配置元數(shù)據(jù)來(lái)配置Spring容器
理解依賴解析
了解自動(dòng)裝配的優(yōu)缺點(diǎn)
在容器中執(zhí)行顯式Bean查找
學(xué)習(xí)不同的Bean實(shí)例化方法
理解指定了作用域的Bean以及可用的作用域
學(xué)習(xí)延遲Bean創(chuàng)建的工作原理
理解生命周期回調(diào)
使用Bean定義配置文件來(lái)創(chuàng)建有條件的Bean配置
2.1.1配置元數(shù)據(jù)
需要向Spring容器提供相關(guān)信息,以便實(shí)例化Bean,并指定如何對(duì)這些Bean進(jìn)行裝配,所提供的信息被稱為配置元數(shù)據(jù)。
配置元數(shù)據(jù)的傳統(tǒng)格式是XML,除此之外還有基于注解和基于java的配置元數(shù)據(jù)。基于XML:
<?xml version="1.0" encoding="UTF-8"?>基于注解:
@Service("accountService")public class AccountServiceImpl implements AccountService { private AccountDao accountDao; @Autowired public void setAccountDao(AccountDao accountDao) { this.accountDao = accountDao; }}@Repository("accountDao")public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {}基于java:
@Configurationpublic class BeanConfig{ @Bean public AccountService accountService(){} @Bean public AccountDao accountDao(){}}2.1.2配置和使用容器
默認(rèn)情況下,每一個(gè)Bean都有一個(gè)被稱作單實(shí)例作用域的單個(gè)實(shí)例。Spring在運(yùn)行時(shí)動(dòng)態(tài)地?cái)U(kuò)展@Configuration并且使用@Bean注解來(lái)重寫工廠方法。因此,不管是從類中多次調(diào)用工廠方法,還是從其他@Configuration類中多次調(diào)用工廠方法,在第1次創(chuàng)建了Bean實(shí)例之后就不會(huì)再創(chuàng)建任何新的Bean實(shí)例,對(duì)于連續(xù)調(diào)用,工廠方法將會(huì)返回相同的Bean實(shí)例。
2.2.1Setter注入是在Bean實(shí)例創(chuàng)建完畢之后執(zhí)行的。
2.2.2構(gòu)造函數(shù)注入是在組件創(chuàng)建期間被執(zhí)行。
2.2.3循環(huán)注入
構(gòu)造函數(shù)注入無(wú)法解決此問題,因?yàn)榻M件創(chuàng)建期間互相依賴,Spring無(wú)法實(shí)例化任一個(gè)Bean;Spring通過使用Setter注入允許循環(huán)注入,因?yàn)榻M件先創(chuàng)建,再設(shè)置屬性。
2.2.4依賴解析過程
Spring容器的啟動(dòng)過程大致分為兩個(gè)主要階段,第一階段容器處理配置元數(shù)據(jù)并建立元數(shù)據(jù)中存在的Bean定義,在該過程中會(huì)對(duì)這些Bean定義進(jìn)行驗(yàn)證。例如,檢查是否向和元素提供了正確的Bean應(yīng)用等。此步驟中Bean并沒有被創(chuàng)建相關(guān)的屬性,也沒有被注入。
第二階段首先完成Bean的創(chuàng)建,然后完成依賴注入。實(shí)際上并不是所有的Bean都被創(chuàng)建,在容器啟動(dòng)期間僅創(chuàng)建了無(wú)狀態(tài)作用域的Bean。
一個(gè)Bean在被完全創(chuàng)建且自己的依賴項(xiàng)被注入之前是不會(huì)作為一個(gè)依賴項(xiàng)被注入到其他的Bean中去的。
2.2.5重寫定義
重寫Spring容器中的Bean定義是可能的,每個(gè)Bean都有身份,而Bean的名稱定義了自己的身份,如果創(chuàng)建了一個(gè)Bean定義,而該Bean的名稱已經(jīng)賦予了其他的定義,那么第二個(gè)定義將重寫第一個(gè)定義。
Spring容器提供了兩種不同形式Bean重寫機(jī)制。第一種重寫發(fā)生在配置元數(shù)據(jù)文件級(jí)別。ApplicationContext創(chuàng)建期間指定這些文件或者類組合在一起。Spring容器將來(lái)自不同配置源的所有Bean合并在一起,合并期間,配置源的順序是非常重要的。如果有兩個(gè)不同的配置源中定義了同名的Bean,那么根據(jù)給定的順序第二個(gè)Bean定義將重寫第一個(gè)Bean定義。
第二種類型的Bean重寫發(fā)生在容器級(jí)別。ApplicationContext可能有父ApplicationContext,在父ApplicationContext實(shí)例和子ApplicationContext實(shí)例中共存兩個(gè)同名的Bean實(shí)例是完全可能的。
在Web應(yīng)用中,通常ContextLoaderListener創(chuàng)建父ApplicationContext,使用DispatcherServlet創(chuàng)建子的ApplicationContext。DispatcherServlet確認(rèn)由ContextLoaderListener創(chuàng)建的ApplicationContext實(shí)例,并在創(chuàng)建自己的ApplicationContext實(shí)例時(shí)將其作為父ApplicationContext。
2.2.6使用depends-on特性
例如一個(gè)執(zhí)行JVM級(jí)別初始化的Bean必須在其他Bean之間被創(chuàng)建,因?yàn)檫@些Bean在被初始化之前必須先完成JVM的初始化。此時(shí),可以在基于XML配置中使用元素的depends-on特性來(lái)制定b和c在a創(chuàng)建之前被創(chuàng)建,如下:
Bean通過名稱進(jìn)行區(qū)分。每一個(gè)Bean至少有一個(gè)名稱,如果開發(fā)人員沒有為其命名,Spring容器將會(huì)為其分配一個(gè)內(nèi)部名稱。通過Bean的名稱,可以從其他Bean定義中或者利用顯示查找從應(yīng)用程序代碼中引用Bean。
在基于XML的配置中使用id特性,將一個(gè)名稱分配的一個(gè)Bean。在相同的XML文件中不能復(fù)制同一個(gè)名稱。然而在其他XML文件中可以將相同的名稱分配給另一個(gè)Bean定義。這種情況下,Bean重啟機(jī)制開始發(fā)揮作用。
2.3.1命名
如果想在Bean定義中為其分配多個(gè)名稱,可以使用name特性,在name特性中可以使用空格、逗號(hào)、分號(hào)來(lái)分離給定Bean定義的多個(gè)名稱。
2.3.2Bean實(shí)例化方法
第一種調(diào)用相關(guān)類中一個(gè)可用的構(gòu)造函數(shù);
第二種調(diào)用靜態(tài)或?qū)嵗S方法;
第三種使用Spring自帶的FactoryBean接口。
public interface FactoryBean { T getObject() throws Exception; Class> getObjectType(); boolean isSingleton();}這是一個(gè)特殊接口,在運(yùn)行時(shí),Spring容器會(huì)發(fā)現(xiàn)實(shí)現(xiàn)了該接口的Bean定義類。如果該類是FactoryBean類型的,則通過調(diào)用其getObject()方法創(chuàng)建該Bean。而所創(chuàng)建的Bean的類型由getObjectType()返回的類型確定,而不是由getObjectType()實(shí)例類確定。該方法通常被Spring Framework所使用。
2.3.3Bean作用域
由Spring容器創(chuàng)建的Bean的生存期被稱為Bean作用域。在默認(rèn)情況下,由Spring容器創(chuàng)建的所有Bean都有Singleton作用域。換句話說(shuō),針對(duì)一個(gè)Bean定義是創(chuàng)建了一個(gè)Bean實(shí)例,并且Spring容器可以在整個(gè)應(yīng)用程序生存期中使用該實(shí)例。當(dāng)不同的Bean與不同的層(控制層、服務(wù)層和數(shù)據(jù)訪問對(duì)象層)相對(duì)應(yīng)時(shí),可以使用Singleton作用域。此時(shí)創(chuàng)建的實(shí)例都是無(wú)狀態(tài)實(shí)例。
2.3.4延遲初始化
默認(rèn)情況下,Spring容器在啟動(dòng)階段創(chuàng)建,該過程被稱為預(yù)先Bean初始化。其優(yōu)點(diǎn)是可以盡早發(fā)現(xiàn)配置錯(cuò)誤。
在另一方面如果存在大量的Bean定義或者一些特殊的Bean,例如hibernate SessionFactory(這些Bean的初始化會(huì)占用大量的時(shí)間),那么初始化會(huì)降低啟動(dòng)速度。一些Bean可能是在特定的場(chǎng)合或備選方案中使用,而其他情況并不需要。在這種情況下,預(yù)先初始化可能會(huì)導(dǎo)致不必要的堆內(nèi)存消耗。
Spring支持延遲Bean初始化。如果開發(fā)人員將Bean配置為延遲創(chuàng)建,那么容器將會(huì)延遲Bean的創(chuàng)建,直到真正需要才創(chuàng)建。通過從一個(gè)已經(jīng)創(chuàng)建的另一個(gè)Bean中的引用,或者在應(yīng)用程序代碼中執(zhí)行顯示查找,都可以觸發(fā)創(chuàng)建。
@Entity@Proxy(lazy = false)@Table(name = "book")public class Book implements Serializable {……}2.3.5生命周期回調(diào)
Bean可以定義回調(diào)方法。這些方法可以在生命期的任何特定時(shí)間點(diǎn)由容器調(diào)用。這些時(shí)間點(diǎn)從Bean實(shí)例化后開始,直到他們定義的作用域終止。這些方法也稱為初始化方法和銷毀方法。
基于XML配置的元素init-method和destory-method特性,他們接收Bean類中的方法名稱作為特性值;
基于注解有PostConstruct和PreDestroy,當(dāng)將這兩個(gè)注解分別放置在init和destory方法之上時(shí),在Bean創(chuàng)建和銷毀時(shí)也會(huì)調(diào)用這兩個(gè)方法。
@PostConstructpublic void init() throws Exception { log.info("Test init start."); ……; log.info("Test init end.");}@PreDestroypublic void destory() throws Exception{ log.info("Test destory start."); ……; log.info("Test destory end.");}第三種選擇是Bean實(shí)現(xiàn)InitializingBean接口,Spring容器在屬性注入完畢之后調(diào)用afterPropertiesSet方法初始化;Bean實(shí)現(xiàn)DisposableBean接口,那么Bean銷毀之前調(diào)用destroy方法。
public interface InitializingBean { void afterPropertiesSet() throws Exception;}public interface DisposableBean { void destroy() throws Exception;}#Spring##程序員#
總結(jié)
以上是生活随笔為你收集整理的factorybean 代理类不能按照类型注入_《Spring入门经典》:使用Spring进行依赖注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何调用日期函数_当前时间等
- 下一篇: springboot 读取配置文件_使用