Spring系列.Bean簡介

Bean屬性配置

Spring在讀取配置文件中bean的metadata後會構造一個個BeanDefination對象。後面Spring會根據這些BeanDefinition建立對象。在配置一個bean的時候咱們能夠配置下面這些元素:java

元素 備註
class 設定類的全限定名
name 設置Bean的名稱,能夠設置多個用逗號分隔
id/name Bean的惟一標識符,全局只能有一個
scope 設置Bean是單例仍是原型,默認單例
constructor arguments 構造方法入參,進行依賴注入
properties 進行依賴注入
autowiring mode 自動注入模式
lazy-initialization mode 只對scope爲單列的bean生效,設置爲true會在getBean()時才建立bean實例
initialization method 設定Bean的初始化方法
destruction method 設定Bean的銷燬方法

除了經過配置信息來建立Bean,Spring還容許經過接口的方式建立用戶在容器外部建立的對象。(經過DefaultListableBeanFactory類的registerSingleton方法和registerBeanDefinition方法)web

In addition to bean definitions that contain information on how to create a specific bean, the ApplicationContextimplementations also permit the registration of existing objects that are created outside the container (by users). This is done by accessing the ApplicationContext’s BeanFactory through the getBeanFactory() method, which returns the BeanFactory DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods. However, typical applications work solely with beans defined through regular bean definition metadata.spring

雖然Spring容器還提供了registerSingleton(..)方法和registerBeanDefinition(..)來註冊單例Bean,可是不建議本身使用這個方法,由於咱們可能在依賴注入以後再註冊了這個Bean。推薦使用配置BeanDefinition的方式來配置Bean。(其實這兩個方法更可能是Spring框架本身使用,在配置文件之外的一些地方再註冊一些Bean到容器中)websocket

關於上面表格中的id屬性和name屬性這邊多說一句。session

id和name屬性均可以用來當作一個bean的標識符,他們兩個的區別是id只能給這個bean指定一個標識符,而name屬性能夠同時給這個bean指定多個標識符(多個標識符之間用,隔開)。下面給出一個配置的列子app

<!--通過下面的配置,bean1,bean二、name一、name二、alias一、alias二、alias3實際上是一個Bean-->
<bean id="bean1,bean2" name="name1,name2" class="com.csx.demo.springdemo.service.MyBean1">
</bean>
<alias name="bean1,bean2" alias="alias1"/>
<alias name="name1" alias="alias2"/>
<alias name="name2" alias="alias3"/>

Bean命名

若是沒有給Bean指定一個標識符,Spring容器會默認給這個Bean設置一個標識符。用戶能夠經過id和name兩個屬性來設置Bean的標識符,這些標識符須要在整個容器範圍內惟一,同時name能夠指定多個用逗號分隔。框架

實例化Bean

實例化Bean通常有四種方式:默認構造函數、待參數的構造函數、靜態工廠類、實例方法建立Bean。須要咱們注意的是Bean的實例化和依賴注入的區別。socket

  1. 默認構造函數方式
<bean id="exampleBean" class="examples.ExampleBean"/>
  1. 帶參數的構造函數
<bean id="Hello2" class="com.csx.personal.web.services.HelloImpl2">
        <constructor-arg index="0" value="chensongxia"/>
        <constructor-arg index="1" value="zhaoru"/>
        <constructor-arg index="2" ref="beanid"/>
    </bean>
  1. 使用靜態工廠類(不推薦使用)
<bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory" factory-method="newInstance">
         <constructor-arg index="0" value="Hello Spring!"/>
    </bean>
    <!-- 使用examples.ClientService這個類的createInstance方法建立bean -->
    <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;
        }
    }
  1. 使用實例方法進行Bean建立
<bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
     </bean>
     <!-- 使用serviceLocator這個Bean的createClientServiceInstance方法建立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;
        }
      }

若是咱們要經過xml的形式配置一個靜態內部類,能夠參考下面的例子ide

For example, if you have a class called SomeThing in the com.example package, and this SomeThing class has a static nested class called OtherThing, the value of the class attribute on a bean definition would be com.example.SomeThing$OtherThing.函數

Bean的Scope

Spring默認支持的Scope

Scopes 描述
singleton 整個IOC容器中只有一個Bean
prototype 每次請求都會生成新的Bean
request 每一個HTTP request都會生成一個新的Bean,只對web系列的ApplicationContext生效
session 每一個session範圍內生成一個新的Bean,只對web系列的ApplicationContext生效
Application ServletContext範圍內生成一個新的Bean,只對web系列的ApplicationContext生效
websocket --

singleton類型的bean定義,在一個容器中只存在一個實例,全部對該類型bean的依賴都引用這一單一實例。

scope爲prototype的bean,容器在接受到該類型的對象的請求的時候(調用getBean方法),會每次都從新 生成一個新的對象給請求方,雖然這種類型的對象的實例化以及屬性設置等工做都是由容器負責的,可是隻要準備完畢,而且對象實例返回給請求方以後,容器就不 在擁有當前對象的引用,請求方須要本身負責當前對象後繼生命週期的管理工做,包括該對象的銷燬。也就是說,容器每次返回請求方該對象的一個新的實例以後, 就由這個對象「自生自滅」了。

單例Bean依賴原型Bean

當一個單例的Bean依賴一個原型Bean時,因爲單例只初始化一次,因此拿到的原型Bean也只是咱們第一次初始化時拿到的Bean,並不能達到咱們想要的效果。此時咱們可使用Spring提供的look-up方式的注入來解決這個問題。

Request, Session, Application, and WebSocket Scopes

這三種Scope只對Web系列的ApplicationContext的生效。能夠視同@RequestScope、@SessionScope和@ApplicationScope使之生效。

自定義Scope

Spring還支持自定義scope,須要時能夠學些下這個特性。

Bean的擴展點(注意和容器擴展點的區別)

Spring提供了一系列接口讓用戶來自定義Bean的屬性(注意和容器擴展點那一個章節的區別),主要的接口有:

  • Lifecycle Callbacks;
  • ApplicationContextAware and BeanNameAware;
  • Other Aware Interfaces;

生命週期回調

所謂生命週期交互就是指在容器建立Bean和銷燬Bean以前作某些操做。在Spring中咱們能夠經過讓Bean實現InitializingBean和DisposableBean接口,使用@PostConstruct和@PreDestroy以及經過以下的配置實現。

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> 
    <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>

若是咱們給一個Bean同時配置了上面多種的初始化和銷燬機制,那麼他們的執行順序以下:

初始化順序

  1. Methods annotated with @PostConstruct (這個方法在構造函數以後執行,是最佳實踐,能夠和Spring API解耦)
  2. afterPropertiesSet() as defined by the InitializingBean callback interface(不建議使用,會耦合Spring API)
  3. A custom configured init() method(普通的xml配置文件中配置的初始化方法)
    析構順序
  4. Methods annotated with @PreDestroy(建議使用)
  5. destroy() as defined by the DisposableBean callback interface (不建議使用)
  6. A custom configured destroy() method (普通的xml文件中配置的銷燬方法)

Spring完整的初始化順序

  1. 容器啓動,實例化全部實現了BeanFactoyPostProcessor接口的類;這步會在任何普通Bean實例化以前加載;
  2. 實例化剩下的單例Bean,對這些Bean進行依賴注入;
  3. 若是Bean有實現BeanNameAware的接口那麼對這些Bean進行調用;
  4. 若是Bean有實現BeanFactoryAware接口的那麼對這些Bean進行調用;
  5. 若是Bean有實現ApplicationContextAware接口的那麼對這些Bean進行調用;
  6. 若是配置有實現BeanPostProcessor的Bean,那麼調用它的postProcessBeforeInitialization方法;
  7. 調用@PostConstruct註解的方法;
  8. 若是Bean有實現InitializingBean接口那麼對這些Bean進行調用;
  9. 若是Bean配置有init屬性,那麼調用它屬性中設置的方法;
  10. 若是配置有實現BeanPostProcessor的Bean,那麼調用它的postProcessAfterInitialization方法;
  11. Bean正常的使用;
  12. 調用@PreDestroy標註的方法;
  13. 調用DisposableBean接口的destory方法;
  14. 調用Bean定義是指定的destroy-method方法;

LifeCycle和SmartLifeCycle接口

Spring提供了LifeCycle接口,實現了這個接口的Bean在Spring容器調用start()和stop()方法的時候能收到Spring的回調信息,分別調用這個Bean的start()和stop()方法。

Aware接口

Spring提供了不少aware接口讓Bean來實現,提示IOC容器,這個Bean須要獲得容器的某些組件或元素。

  • ApplicationContextAware
  • ApplicationEventPublisherAEwvaenrte
  • BeanClassLoaderAware
  • BeanFactoryAware
  • BeanNameAware
  • BootstrapContextAware:Typically available only in JCA aware ApplicationContext instances.
  • LoadTimeWeaverAware
  • MessageSourceAware
  • NotificationPublisherAwareSpring:Spring JMX notification publisher.
  • ResourceLoaderAware
  • ServletConfigAware
  • ServletContextAware
相關文章
相關標籤/搜索