Spring Ioc容器-Bean(一)

Bean的命名

Bean在Ioc容器中能夠有一個或多個名稱,但這些名稱在容器內必須惟一,在Xml中配置id和name屬性就能夠爲Bean起別名。html

<bean id="user" name="zhangsan,lisi" class="com.example.demo.spring.UserBean"/>java

這樣咱們就能夠經過名稱user、zhangsan、lisi獲取UserBean的實例。web

固然若是你沒有給UserBean配置id/name屬性,Spring Ioc容器會未Bean自動生成一個類名首字符小寫的別名。spring

除此以外還可使用<alias name="user" alias="wangwu"></alias配置別名。websocket

Bean的實例化

<bean class=""/>class屬性表明着Ioc要實例化的Bean的類型,一般Ioc容器會經過反射機制調用其無參構造函數直接建立Bean。session

除此以外還能夠配置使用靜態工廠方法或者實例工廠方法來實例化對象。app

/**
 * 使用靜態工廠實例化Bean
 * 配置factory-method屬性
 */
public class StaticFactory {

    private static UserBean userBean = new UserBean();

    public static UserBean createInstance() {
        return userBean;
    }
}
<bean id="user1" class="com.example.demo.spring.StaticFactory" factory-method="createInstance"></bean>

使用class來指定包含static工廠方法的類型,使用factory-method指定建立bean實例的工廠方法。socket

/**
 * 實例工廠方法
 * 配置factory-bean和factory-method屬性
 */
public class InstanceFactory {

    public UserBean createUserBeanInstance() {
        return new UserBean();
    }
}

<bean id="instanceFactory" class="com.example.demo.spring.InstanceFactory"></bean> <bean id="user2" factory-bean="instanceFactory" factory-method="createUserBeanInstance"></bean>ide

使用factory-bean指定要建立Bean實例的方法的Bean的名稱,使用factory-method指定工廠方法名稱。函數

Bean依賴注入

依賴注入指Ioc要建立A的實例,但A內部又依賴於B的實例,依賴注入主要有兩種類型:基於構造函數的依賴注入和基於Setter的依賴注入。

  • 構造函數注入

        基於構造函數的依賴注入主要依賴於<constructor-arg></constructor-ar標籤。

  • 使用type屬性顯式指定了構造函數參數的類型
<bean id="user" class="com.example.demo.spring.UserBean">
    <constructor-arg type="java.lang.Integer" value="15"></constructor-arg>
</bean>

指定type的配置爲Integer而且只有一個參數,因此Ioc在建立UserBean實例是會使用以下的構造函數

 

public UserBean(Integer age) {
    this.age = age;
    System.out.println("1");
}
  • 使用index屬性來顯式指定構造函數參數的索引
    <bean id="user" class="com.example.demo.spring.UserBean">
<!--        <constructor-arg type="java.lang.Integer" value="15"></constructor-arg>-->
        <constructor-arg index="0" value="16"></constructor-arg>
        <constructor-arg index="1" value="張三"></constructor-arg>
    </bean>

指定了有兩個參數,因此會使用以下構造函數

public UserBean(Integer age, String name) {
    this.age = age;
    this.name = name;
    System.out.println("2");
}
  • 使用構造函數參數名稱
<bean id="user" class="com.example.demo.spring.UserBean">
    <constructor-arg name="age" value="85"></constructor-arg>
</bean>

 Setter注入

        使用Setter注入,必須保證要注入的屬性具備setter方法,setter方法能夠利用idea自動生成。主要依賴於<property></property>

<bean id="user" class="com.example.demo.spring.UserBean">
    <property name="name" value="張三"></property>
    <property name="age" value="18"></property>
</bean>
  • list屬性的配置
<bean id="user" class="com.example.demo.spring.UserBean">
    <property name="phone">
        <list>
            <value>123456789</value>
            <value>99999</value>
            <ref bean="user1"></ref>
        </list>
    </property>
</bean>
  • Map屬性的配置
<property name="someMap">
 <map>
 <entry key="an entry" value="just some string"/>
 <entry key ="a ref" value-ref="myDataSource"/>
 </map>
 </property>

Bean的做用域

bean的做用域經過scope屬性配置

scope 描述
singleton Spring Ioc容器中只有一個實例
prototype 每次獲取bena實例都從新建立一個新的
request HTTP 請求的生命週期
session HTTP Session的生命週期
application ServletContext的生命週期
websocket WebSocket的生命週期

Bean的生命週期回調

  • InitializingBean: Bean在初始化時調用,等價於init-method屬性和@PostConstruct註解,若是不指定初始化方法,Spring 默認會調用init()方法
  • DisposableBean:Bean在銷燬時調用,等價於destroy-method屬性和@PreDestroy註解,Spring 默認調用destroy()方法
  • Lifecycle:容器啓動或關閉時回調,該回調是經過 LifecycleProcessor 完成回調
  • ApplicationContextAware:自動獲取ApplicationContext的引用
  • BeanNameAware:獲取該對象在Ioc容器中的名稱,該方法在調用 afterPropertiesSet 或自定義的 init-method 以前調用

除此以外還有其餘的Aware,功能是爲了得到接口申明的依賴

name dependency
ApplicationEventPublisherAware ApplicationContext的事件發佈者
BeanFactoryAware Bean工廠
ServletConfigAware 容器中的ServletConfig(Web容器)
ServletContextAware 容器中運行的ServletContext(Web容器)
BeanClassLoaderAware Bean的類加載器

 Bean的parent屬性

parent屬性用來指定要繼承的配置數據,parent所指向的bean的定義必需要指定abstract屬性爲true,聲明爲抽象定義的Bean不能經過id獲取實例,parent中定義的屬性若是子bean從新配置,則會覆蓋父bean的配置。

<bean id="inheritedTestBean" abstract="true" class="com.example.demo.spring.TestBean">
    <property name="name" value="parent"></property>
    <property name="age" value="1"></property>
</bean>

<bean id="inheritedTestBean" abstract="true">
    <property name="name" value="parent"></property>
    <property name="age" value="1"></property>
</bean>

<bean id="inheritsWithDifferentClass" class="com.example.demo.spring.DrivedTestBean" parent="inheritedTestBean">
    <property name="name" value="override"></property>
    <property name="addr" value="西安"></property>
</bean>

Bean的擴展

  • BeanPostProcessor

BeanPostProcessor接口提供了兩個方法postProcessBeforeInitialization(init以前調用)postProcessAfterInitialization (init以後調用),主要爲了在Spring容器完成實例化、配置和初始化以後實現一些自定義的實例化或依賴解析邏輯等。一個容器中能夠註冊多個BeanPostProcessor,要控制他們的執行順序,只須要繼承Ordered接口。

public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("************postProcessBeforeInitialization*********** + " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("************postProcessAfterInitialization*********** + " + beanName);
        return bean;
    }
}
  • BeanFactoryPostProcessor

     BeanFactoryPostProcessor是用來在beans進行初始化前修改bean的配置元數據。與BeanPostProcessor的主要區別是:BeanPostProcessor對Bean實例進行操做,BeanFactoryPostProcessor是對Bean的配置元數據進行操做。

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("postProcessBeanFactory >>>");
        BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition("message1");
        System.out.println(beanDefinition.getBeanClassName());
    }

    @Override
    public int getOrder() {
        return 1;
    }

    public void init() {
        System.out.println("MyBeanFactoryPostProcessor init");
    }
}
  • PropertyPlaceholderConfigurer

PropertyPlaceholderConfigurer 能夠從單獨獨文件中的 bean 定義外部化屬性值,不一樣的環境中加載不一樣的配置文件。

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="jdbc.properties"></property>
</bean>
<bean id="datasource" class="com.example.demo.spring.DataSource">
    <property name="userName" value="${datasource.userName}"></property>
    <property name="password" value="${datasource.password}"></property>
</bean>

也可使用


<context:property-placeholder location="classpath:com/something/jdbc.properties"/>
  • PropertyOverrideConfigure

用來覆蓋Bean的屬性。

<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
    <property name="locations" value="jdbc.properties"></property>
</bean>
<bean id="datasource" class="com.example.demo.spring.DataSource">
    <property name="password" value="12311"></property>
</bean>

jdbc.properties

datasource.userName=root
datasource.password=root

最終Bean password值會是root被PropertyOverrideConfigurer覆蓋。

FactoryBean

FactoryBean是一個特殊的接口,它不一樣於BeanFactory,BeanFacoty是Spring的工廠,而FactoryBean是容器中的一個特殊bean,能夠建立指定的類型Bean的實例。

public class DataSourceFanctoryBean implements FactoryBean<DataSource> {
    @Override
    public DataSource getObject() throws Exception {
        System.out.println(1);
        DataSource dataSource = new DataSource();
        dataSource.setUserName("張三");
        dataSource.setPassword("123456");
        return dataSource;
    }

    @Override
    public Class<?> getObjectType() {
        return DataSource.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
<bean id="datasource" class="com.example.demo.spring.DataSourceFanctoryBean"></bean>

直接經過beanfactory.getBean("datasource")獲取則是 DataSource 的實例,在id前加 & 則獲取的是 DataSourceFanctoryBean 的實例
相關文章
相關標籤/搜索