Spring(2)——Bean

// Bean例子
public class HelloBean {

    private static final Logger LOG = LoggerFactory
            .getLogger(HelloBean.class);

    private String name;

    private Integer age;
    protected String beanName;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        LOG.info("== 注入Bean屬性 [{}] ==", name);
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public HelloBean() {
        LOG.info("== 構(gòu)造方法 [{}] ==", beanName);
    }

    public HelloBean(String name) {
        this();
        this.name = name;
    }

}

1、XML配置Bean

<beans>

spring配置文件的根元素,包含一個(gè)或多個(gè)bean元素。

<bean>

屬性

default-dependency-check:默認(rèn)的依賴檢查模式。可選四種。

  • none :不進(jìn)行依賴檢查。沒(méi)有指定值的bean屬性僅僅是沒(méi)有設(shè)值。
  • simple:對(duì)基本類型和集合(除了合作者外,比如其他的bean,所有東西)進(jìn)行依賴檢查。
  • object:對(duì)合作者進(jìn)行依賴檢查。
  • all :對(duì)合作者,基本類型和集合都進(jìn)行依賴檢查。

default-lazy-init:默認(rèn)延遲加載。True 或False 。

class:Java Bean 類名。

id:Java Bean在BeanFactory中的唯一標(biāo)識(shí),代碼中通過(guò)BeanFactory獲取JavaBean實(shí)例時(shí)需以此作為索引名稱。

name:同上,如果給bean增加別名,可以通過(guò)name屬性指定一個(gè)或多個(gè)id。

singleton:指定此Java Bean是否采用單例(Singleton)模式,如果設(shè)為“true”,則在BeanFactory作用范圍內(nèi),只維護(hù)此Java Bean的一個(gè)實(shí)例,代碼通過(guò)BeanFactory獲得此Java Bean實(shí)例的引用。反之,如果設(shè)為“false”,則通過(guò)BeanFactory獲取此Java Bean實(shí)例時(shí),BeanFactory每次都將創(chuàng)建一個(gè)新的實(shí)例返回。

abstract:設(shè)定ApplicationContext是否對(duì)bean進(jìn)行預(yù)先的初始化。

parent:定義一個(gè)模板。

autowire:bean自動(dòng)裝配模式??蛇x5種模式。

  • no:不使用自動(dòng)裝配。Bean的引用必須通過(guò)ref元素定義。
  • byName:通過(guò)屬性名字進(jìn)行自動(dòng)裝配。
  • byType:如果BeanFactory中正好有一個(gè)同屬性類型一樣的bean,就自動(dòng)裝配這個(gè)屬性。如果有多于一個(gè)這樣的bean,就拋出一個(gè)致命異常,它指出你可能不能對(duì)那個(gè)bean使用byType的自動(dòng)裝配。如果沒(méi)有匹配的bean,則什么都不會(huì)發(fā)生,屬性不會(huì)被設(shè)置。如果這是你不想要的情況(什么都不發(fā)生),通過(guò)設(shè)置dependency-check="objects"屬性值來(lái)指定在這種情況下應(yīng)該拋出錯(cuò)誤。
  • constructor:這個(gè)同byType類似,不過(guò)是應(yīng)用于構(gòu)造函數(shù)的參數(shù)。如果在BeanFactory中不是恰好有一個(gè)bean與構(gòu)造函數(shù)參數(shù)相同類型,則一個(gè)致命的錯(cuò)誤會(huì)產(chǎn)生。
  • autodetect: 通過(guò)對(duì)bean 檢查類的內(nèi)部來(lái)選擇constructor或byType。如果找到一個(gè)缺省的構(gòu)造函數(shù),那么就會(huì)應(yīng)用byType。

init-method:初始化方法,此方法將在BeanFactory創(chuàng)建JavaBean實(shí)例之后,在向應(yīng)用層返回引用之前執(zhí)行。一般用于一些資源的初始化工作。

destroy-method:銷毀方法。此方法將在BeanFactory銷毀的時(shí)候執(zhí)行,一般用于資源釋放。

factory-bean:通過(guò)實(shí)例工廠方法創(chuàng)建bean,class屬性必須為空,factory-bean屬性必

須指定一個(gè)bean的名字,這個(gè)bean一定要在當(dāng)前的bean工廠或者父bean工廠中,并包含工廠方法。而工廠方法本身通過(guò)factory-method屬性設(shè)置。

factory-method:設(shè)定工廠類的工廠方法。

depends-on:Bean依賴關(guān)系。一般情況下無(wú)需設(shè)定。Spring會(huì)根據(jù)情況組織各個(gè)依賴關(guān)系的構(gòu)建工作。只有某些特殊情況下,如JavaBean中的某些靜態(tài)變量需要進(jìn)行初始化(這是一種BadSmell,應(yīng)該在設(shè)計(jì)上應(yīng)該避免)。通過(guò)depends-on指定其依賴關(guān)系可保證在此Bean加載之前,首先對(duì)depends-on所指定的資源進(jìn)行加載。

子標(biāo)簽

**<property> **
用于設(shè)置一個(gè)屬性。
name屬性:屬性的名稱。
value屬性: 指定bean的屬性值。BeanFactory將自動(dòng)根據(jù)Java Bean對(duì)應(yīng)的屬性類型加以匹配。如果需要將屬性值設(shè)定為null,必須使用<null/>節(jié)點(diǎn)。
ref屬性: 指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。

**<value> **
指定bean的屬性值。

**<ref> **
指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。
bean屬性:指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。
local屬性:指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。(僅在本地(同一個(gè))xml文件里尋找bean。
parent屬性:指定了屬性對(duì)BeanFactory中其他Bean模板的引用關(guān)系。

**<list> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。

**<map> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。

**<set> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。

**<props> **
指定bean的屬性類型為Properties的屬性值。

**<prop> **
key屬性:指定Properties的鍵

**<idref> **
用來(lái)設(shè)置屬性值為容器中其他bean的id 或name。

**<null> **
指定一個(gè)空值。

**<constructor-arg> **
使用構(gòu)造方法注入,指定構(gòu)造方法的參數(shù)。
index屬性:設(shè)置參數(shù)的序號(hào)。
ref屬性:同ref
type屬性:參數(shù)類型。
value屬性:參數(shù)的值。

**<lookup-method> **
lookup方法注入
bean屬性:要注入的bean名
name屬性:要注入的方法名稱

**<replaced-method> **
用來(lái)把已存在的方法實(shí)現(xiàn)替換為其他的實(shí)現(xiàn)。
name屬性:要替換的方法名
replacer屬性:替換者類, 實(shí)現(xiàn)org.springframework.beans.factory.support.MethodReplacer
接口)

**<arg-type> **
方法返回的類型

util命名空間配置
  • 集合:
<util:list> </util:list>
<util:map> </util:map>
<util:set> </util:set>

<util:list id="placeHolderList">
    <value>test</value>
</util:list>
  • properties屬性文件
    util:properties:可以通過(guò)location屬性指定其properties屬性文件的位置
<util:properties> </util:properties>
<util:properties id="settings" location="classpath:config/placeholder.properties"/>

例子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
       default-lazy-init="true">

    <bean name="helloBean" class="com.stepbystep.spring4.samples.beans.HelloBean"
          init-method="initMethod" destroy-method="destroyMethod">
        <property name="name" value="Spring"></property>
        <property name="age" value="0"></property>
    </bean>

    <bean name="helloBean2" class="com.stepbystep.spring4.samples.beans.HelloBean"
          p:name="test" p:age="2"/>
    <bean name="helloBean3" class="com.stepbystep.spring4.samples.beans.HelloBean" p:age="3"/>

    <bean name="helloBean4" class="com.stepbystep.spring4.samples.beans.HelloBean" p:name="${name}" p:age="4"/>

    <!--<bean class="com.stepbystep.spring4.samples.beans.lifecycle.BeanFactoryPostProcessorAdapter"></bean>-->
    <!--<bean class="com.stepbystep.spring4.samples.beans.lifecycle.BeanPostProcessorAdapter"></bean>-->

    <util:list id="list">
        <value>java</value>
        <value>bean</value>
    </util:list>

    <util:map id="map" map-class="java.util.HashMap" >
         <entry key="key1" value-ref="some1"/>
         <entry key="key2" value-ref="some2"/>
         <entry key="key3" value-ref="some3"/>
    </util:map>

    <bean id="someBean" class="cn.itcast.spring._util.SomeBean">
         <property name="someStrArray" ref="strArray"/>
         <property name="someObjArray" ref="objArray"/>
         <property name="someList" ref="list"/>
         <property name="someMap" ref="map"/>
    </bean>
    
</beans>

2、Groovy配置Bean

例子:

import com.stepbystep.spring4.samples.beans.HelloBean

beans{
    helloBean(HelloBean){
        name='GroovyBean'
        age=8
    }
}

3、Bean的實(shí)例化方法

步驟:

(1)實(shí)例化一個(gè)BeanFactory(可以根據(jù)具體需要從BeanFactory的多個(gè)實(shí)現(xiàn)類中實(shí)例化一個(gè));

    BeanFactory beanFactory0 = new DefaultListableBeanFactory();
    BeanFactory beanFactory1 = new ClassPathXmlApplicationContext();
    BeanFactory beanFactory2 = new FileSystemXmlApplicationContext();
    BeanFactory beanFactory3 = new GenericApplicationContext();
    BeanFactory beanFactory4 = new GenericGroovyApplicationContext();
    BeanFactory beanFactory5 = new GenericXmlApplicationContext();
    BeanFactory beanFactory6 = new StaticApplicationContext();
    BeanFactory beanFactory7 = new StaticListableBeanFactory();
    BeanFactory beanFactory8 = new AnnotationConfigApplicationContext();

(2)實(shí)例化一個(gè)BeanDefinitionReader
有兩個(gè)實(shí)現(xiàn)類:XmlBeanDefinitionReader(讀取xml中的bean)GroovyBeanDefinitionReader(讀取groovy中的bean);實(shí)例化時(shí)將BeanFactory作為參數(shù)傳入:

XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
GroovyBeanDefinitionReader beanDefinitionReader = new GroovyBeanDefinitionReader(beanFactory);

(3)實(shí)例化Resource
同樣有多個(gè)實(shí)現(xiàn)類,用于不同的資源文件:

Resource resource0 = new ClassPathResource();
Resource resource1 = new ByteArrayResource();
Resource resource2 = new DescriptiveResource();
Resource resource3 = new FileSystemResource();
Resource resource4 = new InputStreamResource();
Resource resource5 = new PathResource();
Resource resource6 = new UrlResource();
Resource resource7 = new VfsResource();

(4)load資源文件

beanDefinitionReader.loadBeanDefinitions(resource);

(5)最后就是通過(guò)BeanFactory對(duì)bean配置文件中的bean進(jìn)行各種花式操作了,包括獲取一個(gè)bean實(shí)例、讀取properties屬性文件等。


例子:

從xml文件讀取bean:

@Test
public void testBeanFactoryXml(){
    BeanFactory beanFactory = new DefaultListableBeanFactory();

    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
    ClassPathResource resource = new ClassPathResource("spring/hello-bean.xml");
    beanDefinitionReader.loadBeanDefinitions(resource);

    HelloBean bean = beanFactory.getBean("helloBean",HelloBean.class);
    bean.sayHello();

    printBeans((ListableBeanFactory) beanFactory);
}

private void printBeans(ListableBeanFactory beanFactory) {
    StringBuilder sb =new StringBuilder("\n");
    for (String s : beanFactory.getBeanDefinitionNames()) {
        sb.append(s).append("\n");
    }
    LOG.info("beanNames = {}",sb.toString());
    LOG.info("beanNames.size = {}",beanFactory.getBeanDefinitionCount());
}

從Groovy文件讀bean:

@Test
public void testBeanFactoryGroovy(){
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    GroovyBeanDefinitionReader beanDefinitionReader = new GroovyBeanDefinitionReader(beanFactory);
    ClassPathResource resource = new ClassPathResource("spring/helloBean.groovy");
    beanDefinitionReader.loadBeanDefinitions(resource);

    HelloBean bean = beanFactory.getBean(HelloBean.class);
    org.junit.Assert.assertNotNull(bean);
    bean.sayHello();
    LOG.info("beanFactory = {}",beanFactory );
}

4、Bean的生命周期

Spring Bean的完整生命周期從創(chuàng)建Spring容器開(kāi)始,直到最終Spring容器銷毀Bean,這其中包含了一系列關(guān)鍵點(diǎn):

完整的bean生命周期
監(jiān)視Bean的生命周期

為BeanFactory添加BeanPostProcessor

  • 自定義BeanPostProcessor,實(shí)現(xiàn)相應(yīng)的接口和接口方法:

    public class BeanPostProcessorAdapter implements BeanPostProcessor,
    InstantiationAwareBeanPostProcessor,DestructionAwareBeanPostProcessor { ... }
    

    BeanPostProcessor
    初始化前處理:Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    初始化后處理:Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

InstantiationAwareBeanPostProcessor
實(shí)例化前處理:Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
實(shí)例化后處理:boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
實(shí)例化處理屬性:PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

DestructionAwareBeanPostProcessor
銷毀 前處理: void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
boolean requiresDestruction(Object bean);

Bean實(shí)現(xiàn)對(duì)應(yīng)的接口可以在其生命周期的特定時(shí)間回調(diào)相應(yīng)的接口方法:

  • InitializingBean
    void afterPropertiesSet() throws Exception; // 初始化 接口回調(diào)

  • DisposableBean
    void destroy() throws Exception; // 銷毀 接口回調(diào)

  • BeanNameAware
    void setBeanName(String name); // 執(zhí)行Aware操作,讓Bean獲取自己在BeanFactory配置中的名字(根據(jù)情況是id或者name)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • 創(chuàng)建 bean 在經(jīng)歷過(guò) AbstractAutowireCapableBeanFactory#createBea...
    仗劍詩(shī)篇閱讀 2,312評(píng)論 0 1
  • Spring簡(jiǎn)介 spring框架由Rod Johnson開(kāi)發(fā),2004年發(fā)布了Spring框架的第一版。Spri...
    qiuqiu_hz閱讀 1,112評(píng)論 0 15
  • 我會(huì)給你一個(gè)驚喜 我只告訴你是一個(gè)驚喜 你心中會(huì)有猜疑 你會(huì)想象 會(huì)幻想是怎樣的東西 我明白你的好奇 但我只想告訴...
    嘟嘟囔閱讀 236評(píng)論 0 1
  • 在翻完《了不起的蓋茨比》最后一頁(yè)時(shí),我的心中不禁為蓋茨比感到難過(guò)。 一開(kāi)始尼克對(duì)于蓋茨比的了解僅限于那些從天南海北...
    一只快樂(lè)的鷸閱讀 362評(píng)論 0 0

友情鏈接更多精彩內(nèi)容