Spring - 将依赖项注入到ServletContextListener中

27

我想在ServletContextListener中注入一个依赖项。 但是,我的方法不起作用。 我可以看到Spring正在调用我的setter方法,但稍后当调用contextInitialized时,属性为null

这是我的设置:

ServletContextListener:

public class MyListener implements ServletContextListener{

    private String prop;

    /* (non-Javadoc)
     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("Initialising listener...");
        System.out.println(prop);
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
    }

    public void setProp(String val) {
        System.out.println("set prop to " + prop);
        prop = val;
    }
}

web.xml:(这是文件中的最后一个监听器)

<listener>
  <listener-class>MyListener</listener-class>
</listener> 

applicationContext.xml:

<bean id="listener" class="MyListener">
  <property name="prop" value="HELLO" />
</bean>  

输出:

set prop to HELLO
Initialising listener...
null

如何正确实现这个目标?

4个回答

30

狗毒答案(被采纳)是可行的,但由于bean实例化的方式,使测试变得困难。我更喜欢在这个问题中建议的方法:

@Autowired private Properties props;

@Override
public void contextInitialized(ServletContextEvent sce) {
    WebApplicationContextUtils
        .getRequiredWebApplicationContext(sce.getServletContext())
        .getAutowireCapableBeanFactory()
        .autowireBean(this);

    //Do something with props
    ...
}    

3
我知道这条信息有点过时了,但是为了给未来的读者提供参考,当我尝试这个操作时出现了一个"IllegalStateException"错误,并显示No WebApplicationContext found: no ContextLoaderListener registered? 的消息。 - christopher
Chris:我遇到了同样的问题! - Wouter Lievens
@christopher @Wouter 你需要包含Spring的ContextLoaderListener来解决这个问题详见此帖 - asgs

17

我解决了这个问题,通过移除监听器bean并创建一个新的bean来存储我的属性。然后我在监听器中使用以下代码获取属性bean:

@Override
public void contextInitialized(ServletContextEvent event) {

    final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
    final Properties props = (Properties)springContext.getBean("myProps");
}

实例化Bean的方式使得测试变得困难,详见我的回答。 - a.b.d

5

如前所述,ServletContextListener是由服务器创建的,因此它不受Spring管理。

如果您希望收到有关ServletContext的通知,您可以实现该接口:

org.springframework.web.context.ServletContextAware

抱歉,我不明白为什么需要实现 ServletContextAware 接口?我的监听器已经有一个对 ServletContext 的引用,因为它在 ServletContextEvent 中存在。 - dogbane
如果您使用监听器,就无法注入Spring依赖项,因此ServletContextAware是一种替代方法。 - RicoZ

1

你不能让Spring来做这件事,因为它已经被服务器创建了。如果你需要将参数传递给监听器,你可以在web.xml中定义它作为上下文参数。

<context-param> 
        <param-name>parameterName</param-name>
        <param-value>parameterValue</param-value>
    </context-param>

而在监听器中,您可以按以下方式检索它;

 event.getServletContext().getInitParameter("parameterName")

编辑 1:

请参见下面的链接,获取另一种可能的解决方案:

如何使用Spring将依赖项注入HttpSessionListener?


我想传递一个bean,而不是名称-值。 - dogbane
@dogbane 请查看已编辑的帖子。我添加了一个新链接,可能对你的情况也有用。 - fmucar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接