一個Spring IoC容器管理者一個或多個bean。這些 bean 由提供給容器的配置元數據建立,例如以 XML <bean/> 的形式。java
在容器自身的內部,這些bean的定義被表示成BeanDefinition對象,其中包含如下元數據:api
元數據被翻譯爲組成每一個bean定義的一組屬性:併發
class, name, scope, contructor arguments, properties, autowiring mode, lazy-initalization mode, initialization method, destruction method.函數
bean定義包含了如何建立特定bean的信息,做爲它的補充,ApplicationContext的實現也容許用戶註冊容器意外建立、已存在的bean。這須要經過getBeanFactory()方法獲取ApplicationContext的BeanFactory,這個方法返回BeanFactory的實現了DefaultListableBeanFactory。DefaultListableBeanFactory支持經過registerSingleton(...)方法和registerBeanDefinition(...)方法註冊bean。然而,典型的應用程序應該惟一的經過元數據註冊bean。ui
須要儘早註冊 Bean 元數據和手動提供的單例實例,這是爲了使容器在自動裝配和其餘內省步驟能正確的識別它們。雖然在某種程度上可以支持覆蓋現有的元數據和現有的單例實例,可是在運行時註冊新的bean(併發的實時訪問factory)不被官方支持,這可能會產生併發訪問異常和(或)bean容器狀態不一致。this
每一個bean都有一個或多個標識。這些表示必須在持有它的容器中惟一。通常一個bean只有一個標識,可是若是須要多個,額外的標識能夠考慮使用別名。編碼
在XML格式的配置元數據中,可使用id和(或)name屬性做爲bean的標識。只容許指定一個id。按照慣例,name能夠是字母和數字(myBean,fooService等等),可是也能夠包含特殊字符。若是想給bean引入其它別名,能夠在name屬性中聲明它們,用逗號、分號或者空格分隔。在Spring 3.1以前的版本中,id屬性被定義爲一個xsd:ID類型,它限制了可能的字符。從3.1開始,它被定義爲xsd:string類型。須要注意的是bean id的惟一性由容器執行,再也不由XML解析器保證。spa
不要求必須爲bean提供一個名字或id。若是沒有提供名字和id,容器爲bean生成一個惟一的名字。可是,若是想使用名字來引用一個bean(經過使用ref元素或Service Locator方式查找),就必須提供一個名字。不提供名字屬性是由於使用內部bean和自動裝配協做者。翻譯
命名bean的約定使用實例化域(field)名字的標準Java約定。即bean的名字以小寫字母開頭,後面採用駝峯式。例如accountManager、accountService、userDao、loginController等等。code
bean命名的一致性,使得你的配置易於閱讀和理解;而且在使用Spring AOP時,向一組名字相關的bean應用advise時,會有很大的幫助。
在classpath進行組件搜索時,Spring給未命名的組件生成名字,遵循如下規則:使用簡單的類名,並將它的首字母小寫。可是在特殊狀況下類名不只僅是首字母而是前兩個字母都大寫,此時默認的規則將不會生效。而是使用java.beans.Introspector.decapitalize定義的規則。
在bean定義中,經過組合使用一個id值和任意數量的name屬性值,能夠爲bean提供許多名字。這些名字等價與同一bean的別名,在一些狀況下頗有用,例如容許應用程序中的每一個組件經過使用特定於該組件自己的bean名稱來引用公共依賴關係。
在bean實際定義的地方具體說明全部別名是不恰當的。有時須要在其它地方爲bean引入一個別名。這種狀況在一個被分爲許多子系統的大型系統中十分常見,每一個子系統有本身的一組對象定義。在XML格式的配置元數據中,可使用<alias/>元素完成這項任務。
<alias name="fromName" alias="toName"/>
在上例中,在同一容器中的bean被命名爲fromName,在使用了這個別名定義後,可使用toName引用它。
例如,A子系統的配置元數據也許使用名稱subsystemA-dataSource引用一個DataSource。B子系統的配置元數據使用名字subsystemB-dataSource引用一個DataSource。當將這些子系統與主應用組合到一塊兒時,主應用使用myApp-dataSource引用DataSource。爲使這三個名字指向同一對象,能夠在MyApp的配置元數據中加入如下定義:
<alias name="subsystemA-dataSource" alias="subsystemB-dataSource"/> <alias name="subsystemA-dataSource" alias="myApp-dataSource" />
這樣每一個組件和主應用均可以經過惟一的名字引用dataSource,並保證不會與任何其餘定義(有效建立的命名空間)衝突,可是它們都引用同一個bean。
若是使用Java配置,@Bean註解能夠用來提供別名。
bean定義其實就是建立一個或多個對象的規則。在查詢時容器會查看命名bean的規則,並使用由該bean定義封裝的配置元數據建立(或獲取)實際對象。
若是使用XML格式的配置元數據,能夠經過bean元素的class屬性指定將要實例化的對象的類型(class)。 在BeanDefinition實例內部,這個class元素屬性是一個Class類型的域(field/property),這個元素屬性是必需的。可經過如下兩種方式之一使用Class屬性:
若是想配置一個靜態內部類的bean定義,必須使用內部類的二進制名稱。例如,在com.example包中有一個名爲Foo的類,而且這個類有一個靜態內部類名爲Bar,那麼這個bean定義的class屬性應該爲com.example.Foo$Bar。注意在名字中使用$分隔外部類和內部類。
當經過構造函數的方法建立一個bean時,全部正常類均可以使用,並與Spring兼容。即正在開發的類不須要實現任何特定的接口或以特定方式編碼。只需指定bean類便可。可是根據特定bean使用的IoC類型,可能須要一個默認(空)構造函數。
Spring IoC容器幾乎能夠管理您想要管理的任何類;不限於管理真正的JavaBeans。大多數Spring用戶喜歡實際的JavaBean,它們只有默認(無參數)構造函數和屬性以後的恰當的setter和getter方法。但在容器中使用非 bean 形式(non-bean style)的類也是能夠的。好比舊版本的鏈接池,很顯然它與 JavaBean規範不符,但 Spring 也能管理它。
使用XML格式的配置元數據,能夠這樣來指定 bean 類:
<bean id="exampleBean" class="examples.ExampleBean"/> <bean name="anotherExample" class="examples.ExampleBeanTwo"/>
定義使用靜態工廠方法建立的bean時,您可使用class屬性指定包含靜態工廠方法的類和factory-method的屬性,以指定工廠方法自己的名稱。您應該能夠調用此方法(可使用可選的參數),並返回一個活動對象,這個對象隨後將會與經過構造函數建立的對象同樣對待。這種bean定義的一個用途是調用舊代碼中的靜態工廠。
下面的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屬性中指定工廠方法的名字。
<!-- the factory bean, which contains a method called createInstance() --> <bean id="serviceLocator" class="examples.DefaultServiceLocator"> <!-- inject any dependencies required by this locator bean --> </bean> <!-- the bean to be created via the factory bean --> <bean id="clientService" factory-bean="serviceLocator" factory-method="createClientServiceInstance"/>
public class DefaultServiceLocator { private static ClientService clientService = new ClientServiceImpl(); private DefaultServiceLocator() {} 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(); private DefaultServiceLocator() {} public ClientService createClientServiceInstance() { return clientService; } public AccountService createAccountServiceInstance() { return accountService; } }
這種作法代表工廠bean自己也能夠經過依賴注入(DI)進行管理配置。
在Spring文檔中,factory bean是指在Spring容器中配置的工廠類經過實例或靜態工廠方法來建立對象的bean。而 FactoryBean (注意大小寫) 表明了Spring中特定的 FactoryBean。