IT源码网

Spring2:bean的使用讲解

xmjava 2021年06月29日 编程语言 198 0

前言

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>

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


发布评论
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

JQuery插件定义讲解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。