Spring2:bean的使用
转自原文 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>
没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。