2010-05-18 34 views
6

我有了彈簧注入道(下文簡化的)一個單:依賴注入到你的單身

public class MyService<T> implements Service<T> { 
    private final Map<String, T> objects; 
    private static MyService instance; 

    MyDao myDao; 

    public void set MyDao(MyDao myDao) { 
     this. myDao = myDao; 
    } 

    private MyService() { 
     this.objects = Collections.synchronizedMap(new HashMap<String, T>()); 
     // start a background thread that runs for ever 
    } 

    public static synchronized MyService getInstance() { 
     if(instance == null) { 
      instance = new MyService(); 
     } 
     return instance; 
    } 

    public void doSomething() { 
     myDao.persist(objects); 
    } 
} 

我的Spring配置可能會是這樣的:

<bean id="service" class="MyService" factory-method="getInstance"/> 

但是,這將實例啓動期間的MyService。

有沒有一種編程方式來執行MyDao到MyService的依賴注入,但沒有春天管理MyService?

基本上,我希望能夠從我的代碼做到這一點:

MyService.getInstance().doSomething(); 

而有彈性注入MyDao我。

回答

2

如果你想要一個singleton,爲什麼不在Spring配置中定義一個類,並且它自動是一個單例(默認情況下)。

爲了避免在啓動時初始化,你看過春季lazy initialisation?基本上你需要:

lazy-init="true" 

在你的bean定義中。

+0

你必須在需要的地方使用ApplicationContext獲取bean? – Langali 2010-05-18 20:22:31

+0

我會*通常*在初始化時獲得我的一個頂級bean,然後根據需要從頂級bean中引用更多的bean。但你可以做你的建議。 – 2010-05-18 20:29:31

0

正如其他人所提到的,你應該讓Spring來管理你的單身,但如果你想自己管理他們,只是讓春天注入依賴,這樣做:

applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService); 
0

我相信FactoryBean接口是一個很好的選擇。當你需要執行一些初始化邏輯時,這是一個非常好的選擇。例如,要在單獨的線程中啓動內存數據庫或某些後臺進程。

您可以在reference documentation中瞭解更多關於它的信息。

一個演示如何在每次有人想要FactoryBean實現中的bean時實例化數據庫並返回數據源的示例。

@PostConstruct 
void init() { 
    embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath) 
     .addScript(dataPath).setType(embeddedDatabaseType).build(); 
} 


public DataSource getObject() throws Exception { 
    return embeddedDatabase; 
} 

這可以實現工廠邏輯和返回對象之間的鬆散耦合。它在內部被Spring框架大量使用。

如果您希望在第一次使用它時初始化它,請將lazy-initialization設置爲true。

如果您希望代碼與Spring容器進行交互,另一種方法是創建一個實現了接口ApplicationContextAware的工廠。然後,你可以做這樣的事情:

myDao = context.getBean(MyDao.class); 
4

這裏是一個解決方案,創建一個類的靜態工廠方法:

public class MyService { 
    private static MyService instance; 

    private MyDao myDao; 

    public static MyService createInstance(final MyDao myDao) { 
     instance = new MyService(myDao); 
     return instance; 
    } 

    private MyService(final MyDao myDao) { 
     this.myDao = myDao; 
    } 

    public static synchronized MyService getInstance() { 
     return instance; 
    } 

    public void doSomething() { 
     // just do it! 
     myDao.justDoIt(); 
    } 
} 

,並採用彈簧,用來初始化它:

<bean class="my.path.MyService" factory-method="createInstance" scope="singleton"> 
    <constructor-arg ref="reference.to.myDao" /> 
    </bean> 

現在你應該可以這樣做:

MyService.getInstance().doSomething(); 

沒有任何問題。