在Spring WebApplicationInitializer中订购监听器

时间:2012-09-12 08:02:45

标签: java spring

我有一个自定义的ServletContextListener,用于初始化和启动Cron4J调度程序。

public class MainListener implements ServletContextListener {
    @Value("${cron.pattern}")
    private String dealHandlerPattern;

    @Autowired
    private DealMoqHandler dealMoqHandler;
}

我在监听器中自动连接一些对象,如图所示,并希望Spring管理监听器的实例化。我通过WebApplicationInitializer使用程序化的web.xml配置,但到目前为止,Listener没有自动装配(每当我尝试访问所谓的自动装配对象时NullPointerExceptions)。

我已经尝试在添加ContextLoaderListener之后添加我的客户监听器,如下所示:

public class CouponsWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(SpringAppConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        container.addListener(new MainListener()); //TODO Not working
    }

我检查了过去的问题Spring - Injecting a dependency into a ServletContextListenerdependency inject servlet listener,并尝试在我的侦听器的contextInitialized方法中实现以下代码:

    WebApplicationContextUtils
        .getRequiredWebApplicationContext(sce.getServletContext())
        .getAutowireCapableBeanFactory()
        .autowireBean(this);

但是,我得到以下异常:

Exception sending context initialized event to listener instance of class com.enovax.coupons.spring.CouponsMainListener: java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
at org.springframework.web.context.support.WebApplicationContextUtils.getRequiredWebApplicationContext(WebApplicationContextUtils.java:90) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE]

如何在添加监听器之前确保Spring已经完成实例化?

2 个答案:

答案 0 :(得分:2)

我的错误。事实证明原始帖子中的代码是正确的,并且正在以正确的顺序添加侦听器。

问题在于我使用@WebListener注释(Servlet 3.0)注释了我的自定义侦听器。这导致Web应用程序忽略WebApplicationInitializer中的addListener()代码,并实例化Spring的ContextLoaderListener的自定义侦听器AHEAD。

以下代码块说明了ERRONEOUS代码:

@WebListener /* should not have been added */
public class CouponsMainListener implements ServletContextListener {
    @Autowired
    private Prop someProp;
}

答案 1 :(得分:0)

你不能将new与Spring bean一起使用--Java不关心Spring和Spring无法修改new运算符的行为。如果您自己创建对象,则需要自己连接它们。

您还需要小心在初始化期间执行的操作。使用Spring时,请使用此(简化)模型:首先,Spring创建所有bean(为所有bean调用new)。然后它开始连线。

因此,当您开始使用自动装配的字段时,必须格外小心。你不能总是立即使用它们,你需要确保Spring完成所有内容的初始化。

在某些情况下,您甚至无法在@PostProcess方法中使用自动装配的字段,因为Spring因循环依赖而无法创建bean。

所以我的猜测是“每当我试图访问”太早。

出于同样的原因,你不能在WebApplicationContextUtils中使用WebApplicationInitializer:它还没有完成Spring的设置。