Spring中Bean的两种初始化方式
- 是什么
- 为什么
- 但是,如果必须要用多例Bean怎么办?
- 以下为Spring中的多例及初始化
- 再来说说初始化的一些不同细节
- 问题:
- 对Bean的销毁,也就是对容器的销毁
是什么
Spring中的Bean是由IoC容器来管理,这些Bean在同一个容器中是单例模式的,也就是说为无状态的。
这个单例不同于自己写的单例模式:
- 自己写的单例,从加载来说是通过ClassLoader加载并生成单例;
- Spring中的单例,仅仅是在这一个Spring容器中为单例。
无状态:不管哪段代码执行、不管有多少并发执行,这个Bean都是一样的。
有状态:程序运行到不同地方、不同线程执行时,这个Bean都有变化。
为什么
由IoC容器来管理程序中的Bean,能有效提高程序的运行效率,不需要在程序中频繁new对象,提高了对象的复用性。
但是,如果必须要用多例Bean怎么办?
1、可以在每次需要这个多例Bean的时候,手动new;
2、Spring中其实有多例的配置及使用
以下为Spring中的多例及初始化
Spring中bean的scope有六种:singleton(默认),prototype,request,session,global session,application。
- Bean的两个初始化方式
- xml配置
<!-- 单例,scope可以不写 -->
<bean id="singleton" class="com.demo00.spring.bean.init.Demo" scope="singleton"/>
<!-- 多例 -->
<bean id="prototype" class="com.demo00.spring.bean.init.Demo" scope="prototype"/>
- @Bean注解配置
@Bean(name = {"myBean", "myBean2"})
@Scope("prototype")//这个如果不写,为单例
private Demo getTestBean() {
return new Demo("hello bean!");
}
再来说说初始化的一些不同细节
以xml形式来初始化Bean为例,
如果初始化时,想要自定义这个Bean的一些属性,有两种方式:
- 自定义初始化方法
<bean id="initBean" class="com.demo00.spring.bean.init.Demo" init-method="init">
<property name="message" value="为Demo对象中的属性message赋值"/>
</bean>
public class Demo {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void init() {
this.setMessage("初始化方法init()来给属性赋值");
}
}
注意:
- 这里是在xml中的bean标签中添加了一个属性为init-method,这是bean标签自带的,对应的值为在Bean中的方法名。
- 这里,既在xml中添加了要赋值的内容,又在Bean代码中添加了要赋值的内容,根据加载流程知道,最后一个赋值的是代码中的。
加载顺序:
xml
Bean代码中在xml指定的方法
Bean对象
- 通过实现接口InitializingBean并重写afterPropertiesSet()
<bean id="initBean" class="com.demo00.spring.bean.init.Demo2">
<property name="message" value="为Demo2对象中的属性message赋值"/>
</bean>
import org.springframework.beans.factory.InitializingBean;
public class Demo2 implements InitializingBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public void afterPropertiesSet() {
this.setMessage("在这里通过重写方法,在初始化时完成对属性赋值");
}
}
加载顺序:
xml
Bean代码中重写的方法
Bean对象
问题:
如果在xml中配置了Bean属性的初始值,也配置了初始化的方法名,在代码中也实现并重写了afterPropertiesSet()方法,那最后赋值的是哪个?
<bean id="initBean" class="com.demo00.spring.bean.init.Demo2" init-method="init">
<property name="message" value="为Demo2对象中的属性message赋值"/>
</bean>
import org.springframework.beans.factory.InitializingBean;
public class Demo2 implements InitializingBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public void afterPropertiesSet() {
this.setMessage("在这里通过重写方法,在初始化时完成对属性赋值");
}
public void init() {
this.setMessage("初始化方法init()来给属性赋值");
}
}
加载顺序:
xml
Bean代码中重写的方法
Bean代码中在xml指定的方法
Bean对象
对Bean的销毁,也就是对容器的销毁
也有两种方式
- xml配置
<bean id="initBean" class="com.demo00.spring.bean.init.Demo" init-method="init" destroy-method="cleanup">
<property name="message" value="为Demo对象中的属性message赋值"/>
</bean>
public class Demo {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void init() {
this.setMessage("初始化方法init()来给属性赋值");
}
public void cleanup() {
//TODO
System.out.println("销毁这个Bean");
}
}
- 通过实现接口DisposableBean
<bean id="initBean" class="com.demo00.spring.bean.init.Demo2">
<property name="message" value="为Demo2对象中的属性message赋值"/>
</bean>
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Demo2 implements InitializingBean, DisposableBean {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public void afterPropertiesSet() {
this.setMessage("在这里通过重写方法,在初始化时完成对属性赋值");
}
@Override
public void destroy() {
//TODO
System.out.println("销毁这个Bean2");
}
}