为什么韦尔德在雄猫上说"Injection into Listeners is not supported"?



我有一个使用 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。

问题的要求可以概括为:

  1. 应用程序启动时注入 CDI Bean
  2. 用豆子做点什么

解决方案大纲行:

  1. 创建调用BeanManager.fireEvent(new SomeDummyEvent())的 Web 侦听器
  2. 创建一个响应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

最新更新