我有一个自定义的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 ServletContextListener和dependency 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已经完成实例化?
答案 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的设置。