Spring中Bean的两种初始化方式

  • 是什么
  • 为什么
  • 但是,如果必须要用多例Bean怎么办?
  • 以下为Spring中的多例及初始化
  • 再来说说初始化的一些不同细节
  • 问题:
  • 对Bean的销毁,也就是对容器的销毁


是什么

Spring中的Bean是由IoC容器来管理,这些Bean在同一个容器中是单例模式的,也就是说为无状态的。

这个单例不同于自己写的单例模式:

  1. 自己写的单例,从加载来说是通过ClassLoader加载并生成单例;
  2. Spring中的单例,仅仅是在这一个Spring容器中为单例。

无状态:不管哪段代码执行、不管有多少并发执行,这个Bean都是一样的。
有状态:程序运行到不同地方、不同线程执行时,这个Bean都有变化。

为什么

由IoC容器来管理程序中的Bean,能有效提高程序的运行效率,不需要在程序中频繁new对象,提高了对象的复用性。

但是,如果必须要用多例Bean怎么办?

1、可以在每次需要这个多例Bean的时候,手动new;
2、Spring中其实有多例的配置及使用


以下为Spring中的多例及初始化

Spring中bean的scope有六种:singleton(默认),prototype,request,session,global session,application。

  1. 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的一些属性,有两种方式:

  1. 自定义初始化方法
<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对象


  1. 通过实现接口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的销毁,也就是对容器的销毁

也有两种方式

  1. 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");
    }
}
  1. 通过实现接口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");
    }
}

spring bean触发初始化的时机 spring bean初始化方式_赋值