Spring: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

2ClassPathXmlApplicationContext中有一个可变长度的构造函数,用于加载多个.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>


这里出现了两个属性,scopelazy-init

1scope表示的是bean的作用域,有prototyperequestsessionsingleton四种,其中singleton是默认的,表示单例。prototype表示每次创建都会产生一个bean实例。requestsession只在web项目中才会用,其作用域就和web中的requestsession一样

2lazy-init表示的是bean的生命周期,默认为false。当scope=singleton时,bean会在装在配置文件时实例化,如果希望bean在产生时才实例化,可以把lazy-init设置为true。当scope=prototype时,在产生bean时才会实例化它。补充一点,如果希望该配置文件中所有的bean都延迟初始化,则应该beans根节点中使用lazy-init="true"

 

三种注入方式

所谓注入即注入bean中的属性,Spring为用户提供了三种注入方式,settter注入、构造方法注入、注解注入,不过对于Spring的讲解,不讲注解,所以看一下前两种注入方式:

1setter注入,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>


注意这种写法对接口也有效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值