我有一个使用 Resteasy 的 Web 项目(它反过来使用 Weld)并部署到 Tomcat 7.0.22(我把特定版本放在这里,以防这个问题特定于这个版本)。
我有一个看起来像这样的ServletContextListener:
@WebListener
public class ApplicationInitialisationListener implements ServletContextListener {
// create a logger here
@Inject
HealthCheck healthCheck;
@Override
public void contextInitialized(ServletContextEvent event) {
if (healthCheck == null) {
log.error("healthCheck is null");
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
部署到 Tomcat 后,记录了healthCheck is null
,我也注意到日志中的这一行:
<2013-11-13 13:27:40,191> <pack> INFO pool-2-thread-1 org.jboss.weld.environment.tomcat7.Tomcat7Container - Tomcat 7 detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported
问题 1:为什么 CDI 注入在侦听器中不可用?
我查看了这个答案,它说Load on startup via @Startup. There is currently no equivalent to this in CDI.
2:问题1中描述的问题是否是其后果?
问题 3:我正在使用 org.jboss.weld.servlet:weld-servlet:1.2.0.Beta1
。 更高版本中的启动支持是否有任何更新?
我看过的相关问题焊接中的启动类
这是我发现的一种解决方法,可以在应用程序启动时注入 CDI bean。
问题的要求可以概括为:
- 在
- 应用程序启动时注入 CDI Bean
- 用豆子做点什么
解决方案大纲行:
- 创建调用
BeanManager.fireEvent(new SomeDummyEvent())
的 Web 侦听器 - 创建一个响应
SomeDummyEvent
并注入 CDI Bean 的应用程序范围 Bean
示例代码:
@WebListener
public class ApplicationInitialisationListener implements ServletContextListener {
private static final Logger LOG = Logger.getLogger(ApplicationInitialisationListener.class);
@Override
public void contextInitialized(ServletContextEvent event) {
BeanManager beanManager = lookUpBeanManager();
if (beanManager != null) {
beanManager.fireEvent(new SomeDummyEvent());
LOG.info("beanManager fired SomeDummyEvent.");
} else {
LOG.error("beanManager is null. Cannot fire startup event.");
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
public BeanManager lookUpBeanManager() {
try {
// See reference below about how I came up with this
InitialContext iniCtx = new InitialContext();
BeanManager result = (BeanManager) iniCtx.lookup("java:comp/env/BeanManager");
return result;
} catch (NamingException e) {
LOG.error("Could not construct BeanManager.", e);
return null;
}
}
public static class SomeDummyEvent implements Serializable {
}
}
@ApplicationScoped
public class InitializationResourceBean {
private static final Logger LOG = Logger.getLogger(InitializationResourceBean.class);
@Inject
HealthCheck healthCheck;
public void listen(@Observes ApplicationInitialisationListener.SomeDummyEvent event) {
}
@PostConstruct
public void init() {
// Do something with healthCheck
}
@PreDestroy
public void destroy() {
// Do some other thing with healthCheck
}
}
引用:
http://struberg.wordpress.com/tag/cdi/
来自: http://docs.jboss.org/weld/reference/latest-master/en-US/html/environments.html#_tomcat
"支持Tomcat 7和8。上下文激活/停用以及依赖注入到 Servlet 和过滤器中是开箱即用的。注入到 Servlet 侦听器中适用于 Tomcat 7.0.50 及更高版本。
所以也许你可以升级你的雄猫?
现在,所有这些都很容易用 deltaspike servlet 模块完成
@ApplicationScoped
public class InitializationResourceBean {
@Inject
HealthCheck healthCheck;
public void onCreate(@Observes @Initialized ServletContext context) {
//Do initialisation stuff here.
if(HealthCheck != null) {
;
}
}
public void onDestroy(@Observes @Destroyed ServletContext context) {
System.out.println("Destroyed ServletContext: " + context.getServletContextName());
}
}
http://deltaspike.apache.org/documentation/servlet.html