2011-03-09 138 views
9

我試圖使用@Interceptors(SpringBeanAutowiringInterceptor.class)將Spring bean注入到EJB中,但我無法使用我見過的beanRefContext.xml示例。向EJB3注入Spring bean

這裏是我的EJB:

@Stateless 
@Interceptors(SpringBeanAutowiringInterceptor.class) 
public class AlertNotificationMethodServiceImpl implements 
     AlertNotificationMethodService { 

    @Autowired 
    private SomeBean bean; 
} 

我提供了一個beanRefContext.xml如下:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="..."> 

    <!-- Have also tried with ClassPathXmlApplicationContext --> 
    <bean id="context" 
     class="org.springframework.web.context.support.XmlWebApplicationContext"> 
     <property name="configLocations" value="/config/app-config.xml" /> 
    </bean> 

</beans> 

但是,它似乎是重新創建豆,而不是獲取現有的ApplicationContext。我最終得到下面的異常,因爲我的一個bean是ServletContextAware。

java.lang.IllegalArgumentException: Cannot resolve ServletContextResource 
without ServletContext 

當使用SpringBeanAutowiringInterceptor,它不應該獲得的ApplicationContext,而不是創建一個新的?

我也嘗試更改我的web.xml,所以contextConfigLocation指向beanRefContext.xml,希望它會加載我的Spring配置,但最終得到與上面相同的異常。

有誰知道如何正確地做到這一點?我見過的例子似乎使用了我使用的相同的方法,我假設這意味着在調用Interceptor時(或者它應該如何工作並且我誤解了它),bean會被重新創建。

+0

一個有用的鏈接解釋的全過程:http://techo-ecco.com/blog/spring-application-context-hierarchy-and-contextsingletonbeanfactorylocator/ – omartin 2013-02-06 08:42:30

回答

11

當使用SpringBeanAutowiringInterceptor時,是不是應該獲得ApplicationContext而不是創建一個新的?

是的,這實際上是它的功能。它使用ContextSingletonBeanFactoryLocator機制,該機制反過來管理多個ApplicationContext實例作爲靜態單例(是的,有時甚至Spring必須求助於靜態單例)。這些上下文在beanRefContext.xml中定義。

你的困惑似乎源於期望這些上下文與你的webapp的ApplicationContext有任何關係 - 他們不這樣做,他們完全分離。因此,您的web應用程序ContextLoader正在創建和管理基於app-config.xml中的bean定義的上下文,並且ContextSingletonBeanFactoryLocator創建了另一個。除非你告訴他們,他們不會溝通。由於EJB位於該範圍之外,因此EJB無法獲取Web應用程序的上下文。

您需要做的是將您的EJB需要使用的bean從app-config.xml中移出並移動到另一個bean定義文件中。這個提取的bean定義集將構成一個新的ApplicationContext的基礎,它將(a)由EJB訪問,並且(b)將充當web應用程序上下文的父上下文。

爲了激活您的web應用程序的上下文和新上下文之間的父子鏈接,您需要爲web.xml添加額外的<context-param>,名爲parentContextKey。此參數的值應該是在beanRefContext.xml(即在您的示例中爲context)中定義的上下文的名稱。

留在webapp上下文中的bean將能夠引用父上下文中的bean,就像EJB一樣。但是,EJB將無法引用webapp的上下文中的任何內容。

此外,您不能在beanRefContext.xml中使用XmlWebApplicationContext,因爲該類需要了解web應用程序,並且ContextSingletonBeanFactoryLocator無法提供該知名度。那裏應該堅持ClassPathXmlApplicationContext

+0

我終於意識到,我看着這一切錯。當我部署應用程序時,不是創建應用程序上下文,而是在攔截器被調用時創建它。我假定ContextSingletonBeanFactoryLocator能夠找到Web應用程序上下文,但它實際上創建了一個應用程序上下文作爲單例。謝謝你的回答,skaffman,你很聰明 - 就像一個虛擬的Yoda。 – ravun 2011-03-14 15:22:16

+3

@ravun:你必須連接你的環境,是的 – skaffman 2011-03-14 15:23:14