2015-04-22 46 views
3

在所有需要的地方,特別是在非Spring託管類中,注入或傳遞普通的Spring bean不是「掙扎」,而是設置Spring的應用程序上下文在一個靜態變量從任何地方得到它?這樣做允許例如在非Spring託管類(或Hibernate會話工廠)中獲取JdbcTemplate單​​例。有沒有很好的理由不這樣做?Spring的應用程序上下文在任何地方都可用 - 在一個靜態變量中設置應用程序上下文

例如:

@Component 
public class SpringContext implements ApplicationContextAware { 

    private static ApplicationContext applicationContext; 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     SpringContext.applicationContext = applicationContext; 
    } 

    public static JdbcTemplate getJdbcTemplate() { 
     return applicationContext.getBean(JdbcTemplate.class); 
    } 

    public static SessionFactory getSessionFactory() { 
     return applicationContext.getBean(SessionFactory.class); 
    } 

    public static Session getCurrentSession() { 
     SessionFactory sf = applicationContext.getBean(SessionFactory.class); 
     return sf.getCurrentSession(); 
    } 

} 

在另一大類,而不是由Spring管理:

public class MyClass { 

    public Integer method1() { 
     String sql = "select 1 from dual"; 
     Integer n = SpringContext.getJdbcTemplate().queryForObject(sql, Integer.class); 
     return n; 
    } 

} 
+0

Spring的理念是讓所有的容器都能夠管理,所以你的場景永遠不會發生。但是,您有時需要遵守規則。我建議創建實際的單身人士,當你需要他們,並有彈簧注入他們的依賴。看看我的答案[這個問題](http://stackoverflow.com/questions/5010219/singleton-and-autowired-returning-null)。 –

回答

1

此計數器似乎春天的預期用途,並依賴注入的概念。雖然你可以這樣做,但我認爲更好的解決方案是在需要時注入這些bean。我發現一個好的做法是初始化上下文一次,引用一個'root'bean,並且這個bean基本上是應用程序並且包含對系統中其他bean的引用(直接或間接)。

+0

謝謝Brian。我知道依賴注入是一種經過驗證的模式。但我不確定我想成爲那個「囚犯」。我理解IoC和鬆散耦合組件背後的哲學,但在實踐中,我們非常認真地接受一些例外。特別是如果它使開發人員的生活更輕鬆。有時我需要在真正的POJO中加入一點不屬於Spring的管理層的智慧,而不是堅持愚蠢的價值觀者。以這種方式訪問​​Spring bean非常方便。我只是想知道,從純粹的運行時角度來看,它不會導致不好的情況。 – Comencau

0

你想要的是一個單例,即一個只存在一個實例的類,它也是一個Spring管理的單例(一個單例範圍的bean)。幾年前我在使用Spring時發現了一個非常優雅的解決方案。比方說,你單身是這樣的:

public final class MySingletonClass{ 
    private static MySingletonClass instance = new MySingletonClass(); 

    public static MySingletonClass getInstance(){ 
    return instance; 
    } 

    @Autowired 
    private JdbcTemplate jdbcTemplate; 
    @Autowired 
    private SessionFactory sessionFactory; 
    @Autowired 
    private DataSource dataSource; 

    // getters and other methods omitted 
} 

您可以強制Spring來管理這個單隻需在您的應用程序上下文中加入如下一行:

<bean class="com.mypackage.MySingletonClass" factory-method="getInstance"/> 

現在你的單身將上述所有春天自動連接(如果可用的情況下),並且可以通過任何非彈簧配合使用-managed對象管理類:

class MyClass { 
    // Can only be called after Spring initialized. 
    void doSomething() { 
    DataSource ds = MySingletonClass.getInstance().getDataSource(); 
    // ... 
    } 
} 

您認爲需要有一個ACTUA每個對象l單例可以使用上面的模式。這保留了Spring對象生命週期管理和依賴注入的方法,提供了真正的單例對象的安全性。而且,singleton將被Spring管理,因此它的所有依賴關係都將被正確連接,或者應用程序在應用程序啓動時失敗。

+0

謝謝你的回答喬瓦尼。但是,我並不真正看到你的主張的價值。在我的例子中,SpringContext已經是一個單例,因爲它是一個Spring bean(用@Component註解),並且創建bean的Spring的默認範圍是單例。我可以在您的示例中使用SprintContext.getMyBean()(靜態方法)而不是MySingletonClass.getInstance()。getMyBean()。也許,我想念什麼。 – Comencau

+0

我的觀點是你不應該暴露上下文。您應該將應用程序的單例設計爲純Java單例。除了你的單身人士會在窗簾後面的春天進行管理。這樣做的好處是你的應用程序不受Spring的限制,所以如果你最終改變了DI引擎,你可以透明地進行操作。另一個好處是,即使你有一個純Java單例,即只有一個靜態實例存在,但實例仍然由Spring管理,因此你可以使用注入的所有魔力。 –

+0

與你的例子相比,有很小的差異,最顯着的是自動注入而不是手動獲取,這也意味着如果任何bean被錯誤配置,它將立即被Spring捕獲,而不是當你的靜態方法被調用時,它可能在任何點。 –

0

如果你有一個web應用程序,你可以使用Spring的類org.springframework.web.context.support.WebApplicationContextUtils。它提供了獲取根WebApplicationContext的方法。

相關問題