在<bean>标签中添加属性可对bean进行配置,常用配置如下
1.class
为bean配置全限定名,spring会根据该全限定名为bean创建实例并放入容器当中
示例:
在xml文件中配置bean
<!-- 添加一个bean,并配置全限定名 -->
<bean class="com.stlg.bean.TestBeanA"/>
在容器创建完成后查看单例池,可以发现该bean已被实例化并放入单例池中
2.id、name
为bean指定自定义id或别名,可通过id或别名获取到bean(在上个示例处可以发现,未配置id与name时,默认bean名为全限定名 + # + 序号)
示例:
bean的配置:
<!-- 配置id为beanA,另有两个别名testBeanA、aaa -->
<bean id="beanA" name="testBeanA,test" class="com.stlg.bean.TestBeanA"/>
<!-- 仅配置别名 -->
<bean name="bean" class="com.stlg.bean.TestBeanA"/>
容器创建完成后再次查看单例池,可以发现在单例池中默认以bean的id为key,而未配置id时以name为key
分别使用id与name获取bean
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过id获取bean
Object ById = context.getBean("beanA");
//通过name获取bean
Object ByName1 = context.getBean("testBeanA");
Object ByName2 = context.getBean("test");
//输出查看结果
System.out.println("通过id获取:" + ById);
System.out.println("通过name1获取:" + ByName1);
System.out.println("通过name2获取:" + ByName2);
查看结果可以发现无论通过id还是name均可以获取到bean
3.scope
Spring初始提供了两种作用范围,即singleton与prototype,分别为单例与多例模式
单例:该bean仅被实例化一次并放入单例池,此后每次调用时都会获取同一个实例(默认)
多例:每次调用时都会进行实例化,每次调用时获取到的均非同一个实例
示例:
配置bean
<!-- 单例模式bean(默认) -->
<bean id="testBeanA" class="com.stlg.bean.TestBeanA"/>
<!-- 多例模式bean -->
<bean id="testBeanB" class="com.stlg.bean.TestBeanB" scope="prototype"/>
多次获取bean并进行输出
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//多次获取单例bean
Object beanA1 = context.getBean("testBeanA");
Object beanA2 = context.getBean("testBeanA");
//多次获取多例bean
Object beanB1 = context.getBean("testBeanB");
Object beanB2 = context.getBean("testBeanB");
//输出查看结果
System.out.println("单例bean:");
System.out.println("beanA1:" + beanA1);
System.out.println("beanA2:" + beanA2);
System.out.println("多例bean:");
System.out.println("beanB1:" + beanB1);
System.out.println("beanB2:" + beanB2);
查看结果可以发现:单例模式bean两次获取到的实例地址相同,为同一个实例对象;而多例模式bean两次获取到的实例地址不同,不是同一个实例对象。
为再次验证bean被实例化的次数,为bean的无参构造添加输出语句
//单例模式bean的构造方法
public TestBeanA() {
System.out.println("单例模式bean被实例化" + this);
}
//多例模式bean的构造方法
public TestBeanB() {
System.out.println("多例模式bean被实例化" + this);
}
再次进行bean的获取
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//多次获取单例bean
Object beanA1 = context.getBean("testBeanA");
Object beanA2 = context.getBean("testBeanA");
//多次获取多例bean
Object beanB1 = context.getBean("testBeanB");
Object beanB2 = context.getBean("testBeanB");
查看结果可以发现,单例bean的构造方法仅被执行了一次,而多例bean的构造方法被执行了两次
4.lazy-init
配置该bean是否延迟加载,即bean的实例化时机(xml被加载时 或 该bean被获取时)
默认为false(可通过在<beans>标签中设置default-lazy-init属性设置默认值),即容器初始化时实例化;若为true则该bean被获取时实例化(单例模式时,首次获取该bean时实例化)
注:当scope为prototype时,即使该配置为false,也在获取bean时进行实例化
示例:
配置bean,且为了方便查看效果,给它们添加构造方法
<!-- 非延迟加载 -->
<bean id="notLazyInit" class="com.stlg.bean.TestBeanA" lazy-init="false"/>
<!-- 延迟加载 -->
<bean id="lazyInit" class="com.stlg.bean.TestBeanB" lazy-init="true"/>
//非延迟加载bean的构造方法
public TestBeanA() {
System.out.println("非延迟加载bean被实例化" + this);
}
//延迟加载bean的构造方法
public TestBeanB() {
System.out.println("延迟加载bean被实例化" + this);
}
打上断点,进行调试,查看构造方法执行时机
可以发现,在容器初始化时,lazy-init为false的bean已被实例化,而延迟加载的bean还未被实例化。继续执行,观察延迟加载bean的实例化时机
在lazy-init为true的bean被调用获取时,它的构造方法被执行了。
即非延迟加载的bean会在容器初始化时实例化完毕,而延迟加载的bean会在被调用时进行实例化操作。
5.init-method、destroy-method
指定bean的初始化方法与销毁方法,分别在该实例被创建后与销毁前执行
示例:
创建类并添加构造方法、初始化方法、销毁方法,并配置bean
public class TestBean {
//构造方法
public TestBean() {
System.out.println("testBean被实例化" + this);
}
//初始化方法
public void init() {
System.out.println(this + "的初始化方法被执行");
}
//销毁方法
public void destroy() {
System.out.println(this + "的销毁方法被执行");
}
}
<!-- 配置bean初始化方法为init(),销毁方法为destroy() -->
<bean class="com.stlg.bean.TestBean" init-method="init" destroy-method="destroy"/>
由于要测试销毁方法,所以使用ApplicationContext接口的实现类ClassPathXmlApplicationContext进行Xml的加载与容器的初始化,并调用其下的close方法关闭容器
public void test() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//关闭容器,在此之前会执行bean的销毁方法
context.close();
}
调试中查看方法执行时机,并观察容器的状态
可以看到在容器初始化时,由于该bean为单例模式,所以进行了实例化操作,而后它的初始化方法也被执行。继续下一步,查看销毁方法执行时机与容器状态
可以发现在容器关闭前要对bean进行销毁,bean的销毁方法被执行,且容器被关闭