一起來讀官方文件-----SpringIOC(02)
1.3。Bean總覽
Spring IoC容器管理一個或多個bean。這些bean是使用您提供給容器的配置後設資料建立的(例如,以XML 定義的形式 )。
在容器本身內,這些bean定義表示為BeanDefinition物件,其中包含(除其他資訊外)以下後設資料:
包限定的類名:通常,定義了Bean的實際實現類。
Bean行為配置元素,用於宣告Bean在容器中的行為(作用域,生命週期回撥等)。
引用其他bean進行其工作所需的bean。這些引用也稱為協作者或依賴項。
要在新建立的物件中設定的其他配置設定-例如,池的大小限制或在管理連線池的Bean中使用的連線數。
該後設資料轉換為構成每個bean定義的一組屬性。下表描述了這些屬性:
屬性 | 解釋 |
---|---|
類 | 例項化bean |
名稱 | bean名稱 |
生命週期 | bean生命週期 |
建構函式引數 | 依賴注入 |
屬性 | 依賴注入 |
自動注入模式 | 自動注入的合作者 |
延遲初始化模式 | 懶初始化bean |
初始化方法 | 初始化回撥 |
銷燬方式 | 銷燬回撥 |
除了包含有關如何建立特定bean的資訊的bean定義外,這些ApplicationContext實現還允許註冊在容器外部(由使用者)建立的現有物件。這是透過方法訪問ApplicationContext的BeanFactory的getBeanFactory()來完成,該方法返回BeanFactory的DefaultListableBeanFactory實現。DefaultListableBeanFactory 透過registerSingleton(…)和 registerBeanDefinition(…)方法支援此註冊。但是,典型的應用程式僅使用透過常規bean定義後設資料定義的bean。
自定義類 不帶任何註解
public class LearnBean {
public LearnBean(String name) {
}
public String getString(){
return "learnSpring";
}
}
第一種:AnnotationConfigApplicationContext自帶的registerBean方法,可以傳入class和構造引數
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.registerBean(LearnBean.class,"");
annotationConfigApplicationContext.refresh();
LearnBean bean = (LearnBean) annotationConfigApplicationContext.getBean("learnBean");
System.out.println(bean.getString());
第二種:還可以傳入 class和beanDefinition也就是配置後設資料 這個和 getBeanFactory().registerBeanDefinition(..)是一個意思
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext();
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(LearnBean.class);
ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
constructorArgumentValues.addIndexedArgumentValue(0,"111");
rootBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);
annotationConfigApplicationContext.registerBeanDefinition("learnBean",rootBeanDefinition);
annotationConfigApplicationContext.refresh();
LearnBean bean = (LearnBean) annotationConfigApplicationContext.getBean("learnBean");
System.out.println(bean.getString());
注意:如果不寫
annotationConfigApplicationContext.refresh();
就會報錯
Exception in thread "main" java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@68de145 has not been refreshed yet
at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1096)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
at org.springframework.example.DebuggerSpringMain.main(DebuggerSpringMain.java:40)
Bean後設資料和手動提供的單例例項需要儘早註冊,以便容器在自動裝配和其他自省步驟中正確地推理它們。雖然在某種程度上支援覆蓋現有後設資料和現有單例例項,但是在執行時(與對工廠的實時訪問同時)對新bean的註冊不被正式支援,並且可能導致併發訪問異常,bean容器中的狀態不一致或都。
很顯然註冊太晚,就無法和Spring基礎的步驟融合,一些依賴注入無法完成
1.3.1。bean的命名
每個bean具有一個或多個識別符號。這些識別符號在承載Bean的容器內必須唯一。
一個bean通常只有一個識別符號。但是,如果需要多個,則可以將多餘的別名視為別名。
在基於XML配置檔案,您可以使用id屬性,name屬性,或兩者來指定bean識別符號。id屬性使您可以精確指定一個ID。
按照慣例,這些名稱是字母數字(“myBean”,“someService”等),但它們也可以包含特殊字元。如果要為bean引入其他別名,還可以在name屬性中指定它們,並用逗號(,),分號(;)或空格分隔。
作為歷史記錄,在Spring3.1之前的版本中,該id屬性被定義為一種xsd:ID型別,該型別限制了可能的字元。從3.1開始,它被定義為xsd:string型別。
請注意,Bean id唯一性仍由容器強制執行,儘管不再由XML解析器執行。
您不需要為bean 提供name或id。如果不提供 name或id顯式提供,則容器將為該bean生成一個唯一的名稱。
但是,如果您希望透過使用ref元素或服務定位器樣式查詢透過名稱引用那個bean,那麼您必須提供一個名稱。使用內部bean 和 自動裝配合的時候 通常不需要使用名稱。
###### Bean命名約定
約定是在命名bean時將標準Java約定用於例項欄位名稱。
也就是說,bean名稱以小寫字母開頭,並從那裡用駝峰式大小寫。
這樣的名字的例子包括accountManager, accountService,userDao,loginController,等等。
一致地命名Bean使您的配置更易於閱讀和理解。
另外,如果您使用Spring AOP,則在將切點應用於名稱相關的一組bean時,它會很有幫助。
透過在類路徑中進行元件掃描,Spring會按照前面描述的規則為未命名的元件生成Bean名稱:本質上,採用簡單的類名稱並將其初始字元轉換為小寫。
但是,在(不尋常的)特殊情況下,如果有多個字元並且第一個和第二個字元均為大寫字母,則會保留原始大小寫。
這些規則與java.beans.Introspector.decapitalize(由Spring在此處使用)定義的規則相同。
在Bean定義之外別名Bean
在bean定義本身中,可以透過使用id屬性指定的最多一個名稱和屬性中任意數量的其他名稱的組合來為bean提供多個名稱name。這些名稱可以是同一個bean的等效別名,並且在某些情況下很有用,例如,透過使用特定於該元件本身的bean名稱,讓應用程式中的每個元件都引用一個公共依賴項。
但是,在實際定義bean的地方指定所有別名並不總是足夠的。有時需要為在別處定義的bean引入別名。在大型系統中通常是這種情況,在大型系統中,配置在每個子系統之間分配,每個子系統都有自己的物件定義集。在基於XML的配置後設資料中,您可以使用元素來完成此任務。以下示例顯示瞭如何執行此操作:
<alias name="fromName" alias="toName"/>
在這種情況下,(在同一個容器中)名為fromName的bean在使用了這個別名定義之後,也可以被稱為toName。
例如,
子系統A的配置後設資料可能引用一個名為subsystem-DataSource的資料來源。
子系統B的配置後設資料可以引用名為subsystembl-DataSource的資料來源。
在編寫使用這兩個子系統的主應用程式時,主應用程式以myApp-dataSource的名稱引用資料來源。
要讓這三個名稱引用同一個物件,您可以在配置後設資料中新增以下別名定義:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
現在,每個元件和主應用程式都可以透過唯一的名稱引用資料來源,並且可以保證不與任何其他定義衝突(有效地建立名稱空間),但是它們引用的是同一bean。
Java-configuration
如果使用Java-configuration,則@Bean註解可用於提供別名。有關詳細資訊,請參見使用@Bean註解。
1.3.2。例項化bean
bean定義本質上是建立一個或多個物件的訣竅。當被請求時,容器檢視已命名bean的配方,並使用該bean定義封裝的配置後設資料來建立(或獲取)實際物件。
如果使用基於XML的配置後設資料,則可以在元素的class屬性中指定要例項化的物件的型別(或類)。此 class屬性(在內部是例項的Class屬性BeanDefinition)通常是必需的。
以下兩種情況會用到Class屬性:
通常,在容器本身透過反射呼叫其建構函式直接建立bean的情況下,
指定要構造的bean類,這在某種程度上等同於使用new運算子的Java程式碼。
要指定包含為建立物件而呼叫的靜態工廠方法的實際類,
在容器呼叫類上的靜態工廠方法來建立bean的情況下就不太常見了。
從靜態工廠方法呼叫返回的物件型別可以是相同的類,也可以完全是另一個類。
內部類名稱
如果希望為靜態巢狀類配置bean定義,則必須使用巢狀類的二進位制名稱。
例如,如果你在com中有一個叫做什麼的類。
這個東西類有一個名為OtherThing的靜態巢狀類,
bean定義上的class屬性的值將是com.example.SomeThing$OtherThing。
請注意名稱中使用了$字元來分隔巢狀的類名和外部類名。
<bean id="innerClass1" class="org.springframework.example.config.MyBean$InnerClass"/>
用建構函式例項化
當透過構造方法建立一個bean時,所有普通類都可以被Spring使用並與之相容。也就是說,正在開發的類不需要實現任何特定的介面或以特定的方式進行編碼。只需指定bean類就足夠了。但是,根據您用於該特定bean的IoC的型別,您可能需要一個預設(空)建構函式。
Spring IoC容器幾乎可以管理您要管理的任何類。它不僅限於管理真正的JavaBean。大多數Spring使用者更喜歡實際的JavaBean,它僅具有預設(無引數)建構函式,並具有根據容器中的屬性建模的適當的setter和getter。您還可以在容器中具有更多奇特的非bean樣式類。例如,如果您需要使用絕對不符合JavaBean規範的舊式連線池,則Spring也可以對其進行管理。
使用基於XML的配置後設資料,您可以如下指定bean類:
<bean id="exampleBean" class="examples.ExampleBean"/>
<bean name="anotherExample" class="examples.ExampleBeanTwo"/>
有關用於向建構函式提供引數(如果需要)並在構造物件之後設定物件例項屬性的機制的詳細資訊,請參見 注入依賴項。
用靜態工廠方法例項化
在定義使用靜態工廠方法建立的bean時,請使用class屬性指定包含static工廠方法的類,並使用命名factory-method為屬性的屬性來指定工廠方法本身的名稱。您應該能夠呼叫此方法(使用可選引數,如稍後所述)並返回一個活動物件,該物件隨後將被視為已透過建構函式建立。這種bean定義的一種用法是static用舊程式碼呼叫工廠。
以下bean定義指定透過呼叫工廠方法來建立bean。該定義不指定返回物件的型別(類),而僅指定包含工廠方法的類。在此示例中,該createInstance() 方法必須是靜態方法。以下示例顯示如何指定工廠方法:
<bean id="clientService"
class="examples.ClientService"
factory-method="createInstance"/>
public class ClientService {
private static ClientService clientService = new ClientService();
private ClientService() {}
public static ClientService createInstance() {
return clientService;
}
}
使用例項工廠方法例項化
類似於透過靜態工廠方法進行例項化,使用例項工廠方法進行例項化會從容器中呼叫現有bean的非靜態方法來建立新bean。要使用此機制,請將class屬性留空,並在factory-bean屬性中指定當前(或父容器或祖先容器)中包含要建立物件的例項方法的bean的名稱。使用factory-method屬性設定工廠方法本身的名稱。以下示例顯示瞭如何配置此類Bean:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
</bean>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
}
一個工廠類也可以包含一個以上的工廠方法,如以下示例所示:
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
<!-- inject any dependencies required by this locator bean -->
</bean>
<bean id="clientService"
factory-bean="serviceLocator"
factory-method="createClientServiceInstance"/>
<bean id="accountService"
factory-bean="serviceLocator"
factory-method="createAccountServiceInstance"/>
public class DefaultServiceLocator {
private static ClientService clientService = new ClientServiceImpl();
private static AccountService accountService = new AccountServiceImpl();
public ClientService createClientServiceInstance() {
return clientService;
}
public AccountService createAccountServiceInstance() {
return accountService;
}
}
這種方法表明,工廠Bean本身可以透過依賴項注入(DI)進行管理和配置。詳細資訊,請參見依賴性和配置。
在Spring文件中,“ factory bean”是指在Spring容器中配置並透過例項或 靜態工廠方法建立物件的bean 。相反, FactoryBean(注意大寫)是指特定於Spring的 FactoryBean 實現類。
確定Bean的執行時型別
確定特定bean的執行時型別並非易事。Bean後設資料定義中的指定類只是初始類引用,可能與宣告的工廠方法結合使用,或者是FactoryBean可能導致Bean的執行時型別不同的類,或者在例項的情況下根本不設定-級別工廠方法(透過指定factory-bean名稱解析)。另外,AOP代理可以使用基於介面的代理包裝bean例項,而目標Bean的實際型別(僅是其實現的介面)的暴露程度有限。
找出特定bean的實際執行時型別的推薦方法是BeanFactory.getType呼叫指定的bean名稱。這考慮了上述所有情況,並返回了BeanFactory.getBean要針對相同bean名稱返回的物件的型別。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/506/viewspace-2826227/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一起來讀官方文件-----SpringIOC(04)Spring
- 一起來打靶 02
- 通讀Python官方文件之cgitbPythonGit
- 通讀Python官方文件之ThreadingPythonthread
- go package官方文件閱讀方式GoPackage
- 來了!Python官方文件中文版Python
- 一起來解讀LIS吧!
- C# 官方文件導讀及推薦書單C#
- Django官方文件Django
- nmap官方文件
- 史上最全cudnn 安裝教程,來源與官方文件DNN
- Python 官方文件解讀(1):66 個內建函式Python函式
- 【pytest官方文件】解讀fixtures - 1.什麼是fixtures
- 【pytest官方文件】解讀fixtures - 2. fixtures的呼叫方式
- OKHttp 官方文件【一】HTTP
- OKHttp 官方文件【二】HTTP
- [譯] 每天一段 Spring 5 官方文件(5.1.4.RELEASE)—— Spring Framework Overview 02SpringFrameworkView
- Oracle OCP(33):官方文件Oracle
- kafka官方幫助文件Kafka
- Moya官方文件翻譯
- [譯] AsyncDisplayKit/Texture 官方文件(2)
- docker官方文件翻譯3Docker
- [譯] AsyncDisplayKit/Texture 官方文件(1)
- Python 官方文件:入門教程Python
- docker官方文件翻譯5Docker
- docker官方文件翻譯2Docker
- docker官方文件翻譯1Docker
- UNITY官方文件:事件函式Unity事件函式
- 【Python】官方文件中文版Python
- rabbitmq 官方文件翻譯-2MQ
- docker官方文件翻譯4Docker
- 面向官方文件學習Pytoch
- Kafka官方文件V2.7Kafka
- 【pytest官方文件】解讀Skipping test functions,跳過測試用例詳解Function
- SpringIOC原理分析Spring
- HTTPie 官方文件中文翻譯版HTTP
- [譯] Retrofit官方文件最佳實踐
- iOS 如何分析crash log 官方文件iOS