Spring2:bean的使用


前言

Spring最基礎的功能就是一個bean工廠,所以本文講解的是Spring生成bean的種種方法及細節,Spring配置文件的名字是bean.xml,定義幾個類:

一個Person類:

public class Person
{
    private String     personName; // 人的名字
    private int        personAge;    // 人的年齡    
    
    public Person(String personName, int personAge)
    {
        this.personName = personName;
        this.personAge = personAge;
    }

    public String getPersonName()
    {
        return personName;
    }
    
    public void setPersonName(String personName)
    {
        this.personName = personName;
    }
    
    public int getPersonAge()
    {
        return personAge;
    }

    public void setPersonAge(int personAge)
    {
        this.personAge = personAge;
    }

    public String toString()
    {
        return "personName = " + personName + ", personAge = " + personAge;
    }
}

一個Family類,里面持有Person的引用:

public class Family
{
    private Person person;
    private String familyName;

    public Family(Person person, String familyName)
    {
        this.person = person;
        this.familyName = familyName;
    }

    public String toString()
    {
        return person.toString() + ", familyName = " + familyName;
    }
}

一個單例類:

public class SingletonClass
{
    private SingletonClass instance = new SingletonClass();
    
    private SingletonClass(){}
    
    public SingletonClass getInstance()
    {
        return instance;
    }
}

一個空的類,為了測試初始化和銷毀用的:

public class EmptyClass
{
    static
    {
        System.out.println("Enter EmptyClass.static block");
    }
    
    public EmptyClass()
    {
        System.out.println("Enter EmptyClass.construct()");
    }
    
    public void init()
    {
        System.out.println("Enter EmptyClass.init()");
    }
    
    public void destory()
    {
        System.out.println("Enter EmptyClass.destory()");
    }
}

一個集合類,為了演示集合注入:

public class CollectionClass
{
    private List<String> list;
    private Map<Family, Person> map;
    private int[] ints;
    
    public List<String> getList()
    {
        return list;
    }
    
    public void setList(List<String> list)
    {
        this.list = list;
    }
    
    public Map<Family, Person> getMap()
    {
        return map;
    }
    
    public void setMap(Map<Family, Person> map)
    {
        this.map = map;
    }

    public int[] getInts()
    {
        return ints;
    }

    public void setInts(int[] ints)
    {
        this.ints = ints;
    }
}

 

最簡單的bean實例化

bean.xml中注入這個bean,以Person類為例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="person" class="com.xrq.bean.Person" />
    
</beans>

main函數這么寫:

public static void main(String[] args)
{
    ApplicationContext ctx = 
            new ClassPathXmlApplicationContext("spring.xml");
    Person person1 = (Person)ctx.getBean("person");
    Person person2 = (Person)ctx.getBean("person");
    System.out.println(person1 == person2);
}

運行結果為true,也就是說Spring默認以單例的形式給開發者構造出指定的bean。另外有兩點要注意:

1、同一個spring.xml中不可以定義兩個id相同的bean

2、ClassPathXmlApplicationContext中有一個可變長度的構造函數,用於加載多個.xml中的bean,如果bean中有id相同,那么id相同的bean,后加載的會覆蓋先加載的

 

bean的作用域及生命周期

代碼不動,把bean.xml文件修改一下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="person" class="com.xrq.bean.Person" scope="prototype"
        lazy-init="true"/>
    
</beans>

這里出現了兩個屬性,scope和lazy-init:

1、scope表示的是bean的作用域,有prototype、request、session、singleton四種,其中singleton是默認的,表示單例。prototype表示每次創建都會產生一個bean實例。request和session只在web項目中才會用,其作用域就和web中的request和session一樣

2、lazy-init表示的是bean的生命周期,默認為false。當scope=singleton時,bean會在裝在配置文件時實例化,如果希望bean在產生時才實例化,可以把lazy-init設置為true。當scope=prototype時,在產生bean時才會實例化它。補充一點,如果希望該配置文件中所有的bean都延遲初始化,則應該在beans根節點中使用lazy-init="true"

 

三種注入方式

所謂注入即注入bean中的屬性,Spring為用戶提供了三種注入方式,settter注入、構造方法注入、注解注入,不過對於Spring的講解,不講注解,所以看一下前兩種注入方式:

1、setter注入,bean.xml的寫法為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="person" class="com.xrq.bean.Person">
        <property name="personName" value="Alice"/>
        <property name="personAge" value="10" />
    </bean>    
</beans>

2、構造方法注入,bean.xml的寫法為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    
    <bean id="family" class="com.xrq.bean.Family">
        <constructor-arg name="person" ref="person" />
        <constructor-arg name="familyName" value="friendly" />
    </bean>
    
    <bean id="person" class="com.xrq.bean.Person">
        <property name="personName" value="Alice"/>
        <property name="personAge" value="10" />
    </bean>    
</beans>

這里故意把family的定義寫在person的定義上面,說明即使前面的beanA持有beanB的引用,把beanA定義在beanB前面也不影響

 

集合注入

spring對於集合屬性的支持非常好,以CollectionClass為例,看下如何配置bean.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="collectionClass" class="com.xrq.bean.CollectionClass">
        <property name="list">
            <list>
                <value>111</value>
                <value>222</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="111">
                    <bean class="com.xrq.bean.Person">
                        <property name="personName" value="Mike"/>
                        <property name="personAge" value="11" />
                    </bean>
                </entry>
            </map>
        </property>
        <property name="ints">
            <array>
                <value>333</value>
                <value>444</value>
            </array>
        </property>
    </bean>
</beans>

 

工廠方式生成類

Spring雖然可以指定bean以單例的方式生成出來,但是每次都要用getBean方法獲取類的實例非常麻煩,有辦法像單例模式一樣使用XXX.getInstance()就好了,不過還真有,以SingletonClass作為例子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="singletonClass" class="com.xrq.bean.SingletonClass"
        factory-method="getInstance">
    </bean>
    
</beans>

這樣,我們就可以使用單例的方式去調用這個類了,如果類里面有一些私有屬性,還可以注入的方式在生成這個bean的時候就注入進去,非常方便

 

init-method和destory-method

有時候我們希望,在某個bean加載的時候做一些事情,銷毀的時候做一些事情(是不是想到了Servlet),所以我們可以自定義初始化和銷毀的方法EmptyClass這個類,bean.xml的配置為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
        
    <bean id="emptyClass" class="com.xrq.bean.EmptyClass" 
        init-method="init" destroy-method="destory"/>
</beans>

注意兩點:

1、實例化類的時候,幾個方法的加載順序為靜態資源->構造方法->初始化方法

2、觸發destory()方法的調用可以使用"((ClassPathXmlApplicationContext)ctx).close();",注意scope="prototype"是不會觸發destory()的,沒有為什么,設計就是這樣

 

父子類繼承關系

有時候我們有要求,一個類是某一個類/抽象類的子類,可以這么做:

public abstract class AbstractClass
{

}
public class ImplClass extends AbstractClass
{

}

此時bean.xml要這么寫:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    
    <bean id="abstractClass" class="com.xrq.bean.abstractClass" abstract="true"/>
    <bean id="implClass" class="com.xrq.bean.ImplClass" parent="abstractClass" />
</beans>

注意這種寫法對接口也有效。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM