1. 程式人生 > >Spring中Bean的初始化及銷燬方式

Spring中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程式碼中添加了要賦值的內容,根據載入流程知道,最後一個賦值的是程式碼中的。

載入順序:

  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屬性的初始值,也配置了初始化的方法名,在程式碼中也實現並重寫了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()來給屬性賦值");
    }
}

載入順序:

對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");
    }
}

在這裡插入圖片描述