3

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

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

    @Autowired
    private DealMoqHandler dealMoqHandler;
}

如图所示,我正在自动装配侦听器中的一些对象,并希望 Spring 管理侦听器的实例化。我正在使用程序化 web.xml 配置WebApplicationInitializer,但到目前为止,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 ServletContextListener and dependency injection 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 已经完成了实例化?

4

2 回答 2

2

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

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

以下代码块说明了错误代码:

@WebListener /* should not have been added */
public class CouponsMainListener implements ServletContextListener {
    @Autowired
    private Prop someProp;
}
于 2012-09-12T08:28:02.947 回答
0

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

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

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

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

所以我的猜测是“每当我尝试访问时”为时过早。

出于同样的原因,你不能WebApplicationContextUtilsWebApplicationInitializer: 它还没有完成设置 Spring,但是。

于 2012-09-12T08:28:56.723 回答