2011-03-09 102 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