【Spring實戰】—— 3 使用facotry-method創建單例Bean總結


如果有這樣的需求

  1 不想再bean.xml加載的時候實例化bean,而是想把加載bean.xml與實例化對象分離。

  2 實現單例的bean

以上的情況,都可以通過工廠方法factory-method來創建bean

這樣再加載bean.xml時,不會直接實例化bean,而是當調用factory-method所指的方法時,才開始真正的實例化。

  首先看一下傳統的單例模式的實現方式:

  1 最原始的實現單例模式的方法(存在線程不安全):

public class SingletonOne {
    private static SingletonOne instance = null;
    private SingletonOne() {}
    public static SingletonOne getInstance() {
        if (instance == null) {
            instance = new SingletonOne(); 
        }
        return instance;
    }
}    

  但是這種方法有一個弊端,就是存在線程的不安全!

  比如當兩個線程同時進入if(instance == null)時,一個線程判斷了當前為空,然后切換到另一個線程,這個線程也判斷為空。然后切換回第一個線程,進行實例化,再切換到第二個線程,進行實例化。這樣就存在了兩個實例。

  2 通過關鍵字Synchronized強制線程同步 

package com.something.singleton;
public class SingletonTwo {
    private static SingletonTwo instance = null;
    private SingletonTwo() {}
    public static synchronized SingletonTwo getInstance() {
        if (instance == null) {
            instance = new SingletonTwo();
        }
        return instance;
    }
}

  這樣當線程進行到getInstance會同步的進行,不會有線程安全問題,但是不僅僅是實例化,每次調用也需要同步,這樣就會造成很多資源的浪費。

  3 通過靜態內部類進行單例

public class SingletonThree {
    private static class SingletonHolder{
        static SingletonThree instance = new SingletonThree();
    }
    
  private SingletonThree() {} public static SingletonThree getInstance() { return SingletonHolder.instance; } }

  這種方法時最推薦的一種方法,由於Java的調用機制,SingletonHolder只有在調用getInstance的時候才會加載,而內部的靜態類只會被加載一次,因此又是線程安全的。

  總結起來

  第一種方法,是存在線程安全問題的。

  第二種方法,則消耗了一定的資源。

  第三種方法,比較推薦。

 

通過spring的factory-method來創建單例的bean

  首先通過靜態內部類創建一個單例對象

package com.spring.test.factorymethod;

public class Stage {
    public void perform(){
        System.out.println("演出開始...");
    }
    private Stage(){
        
    }
    private static class StageSingletonHolder{
        static Stage instance = new Stage();
    }
    public static Stage getInstance(){
        return StageSingletonHolder.instance;
    }
}

  在spring配置文件中指定加載的方法getInstance

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     <bean id="theStage" class="com.spring.test.factorymethod.Stage"
         factory-method="getInstance"></bean>
</beans>

  通過應用上下文調用bean獲取實例

package com.spring.test.factorymethod;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
        Stage stage = ((Stage)ctx.getBean("theStage"));//.getInstance();
        stage.perform();
    }
}

  執行結果

一月 24, 2015 6:38:18 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@512dbd1a: startup date [Sat Jan 24 18:38:18 CST 2015]; root of context hierarchy
一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean.xml]
一月 24, 2015 6:38:19 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d1879ea: defining beans [duke,sonnet29,poeticDuke,theStage]; root of factory hierarchy
演出開始...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM