@Autowired在ServletContextListener中

我hava aclass InitApp

@Component public class InitApp implements ServletContextListener { @Autowired ConfigrationService weatherConfService; /** Creates a new instance of InitApp */ public InitApp() { } public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println(weatherConfService); } public void contextDestroyed(ServletContextEvent servletContextEvent) { } } 

和web.xml中的监听器:

   com.web.Utils.InitApp   org.springframework.web.context.ContextLoaderListener  

confService打印 – > null有什么问题?

当我遇到同样的问题时,我想到了几个想法。

第一个是使用Spring utils从侦听器中的Spring上下文中检索bean:

例如:

 @WebListener public class CacheInitializationListener implements ServletContextListener { /** * Initialize the Cache Manager once the application has started */ @Override public void contextInitialized(ServletContextEvent sce) { CacheManager cacheManager = WebApplicationContextUtils.getRequiredWebApplicationContext( sce.getServletContext()).getBean(CacheManager.class); try { cacheManager.init(); } catch (Exception e) { // rethrow as a runtime exception throw new IllegalStateException(e); } } @Override public void contextDestroyed(ServletContextEvent sce) { // TODO Auto-generated method stub } } 

如果您只有一个或两个bean,这可以正常工作。 否则它会变得单调乏味。 另一个选择是显式调用Spring的Autowire实用程序:

 @WebListener public class CacheInitializationListener implements ServletContextListener { @Autowired private CacheManager cacheManager; /** * Initialize the Cache once the application has started */ @Override public void contextInitialized(ServletContextEvent sce) { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); try { cacheManager.init(); } catch (Exception e) { // rethrow as a runtime exception throw new IllegalStateException(e); } } @Override public void contextDestroyed(ServletContextEvent sce) { // TODO Auto-generated method stub } } 

这两个解决方案中的警告是,必须首先加载Spring上下文,然后才能使用其中任何一个。 鉴于无法使用@WebListener定义侦听器顺序,请确保在web.xml定义Spring ContextLoaderListener以强制首先加载它(Web描述符中定义的侦听器在@WebListener定义的侦听器之前加载)。

通过声明

  com.web.Utils.InitApp  

在您的web.xml中,您告诉容器初始化并注册InitApp实例。 因此,该对象不是由Spring管理的,你不能@Autowired任何东西。

如果您的应用程序上下文设置为组件扫描com.web.Utils包,那么您将拥有一个未注册为容器侦听器的InitApp bean。 因此,即使你的其他bean将是@ @Autowired ,servlet容器也不会命中它。

这是权衡。

如果对Servlet 3.0使用ServletContainerInitializerWebApplicationInitializer进行编程配置,则有一些解决方法。 你不会使用@Autowired ,你只需要用于设置实例的setter / getter。

这是一个例子

 class SpringExample implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { WebApplicationContext context = ...; SomeBean someBean = context.getBean(SomeBean.class); CustomListener listener = new CustomListener(); listener.setSomeBean(someBean); // register the listener instance servletContext.addListener(listener); // then register DispatcherServlet and ContextLoaderListener, as appropriate ... } } class CustomListener implements ServletContextListener { private SomeBean someBean; public SomeBean getSomeBean() { return someBean; } public void setSomeBean(SomeBean someBean) { this.someBean = someBean; } @Override public void contextInitialized(ServletContextEvent sce) { // do something with someBean } @Override public void contextDestroyed(ServletContextEvent sce) { } } 

请注意,Spring有一些非常复杂的WebApplicationInitializer自定义实现。 你真的不需要自己直接实现它。 这个想法保持不变,只是在inheritance层次结构中更深层次。

正如其他人所说,这个监听器通过web servlet(tomcat)上下文(不是Spring容器)进行观察,并被告知servlet启动/关闭。

由于它是由Spring容器外部的servlet创建的,因此不受Spring管理,因此@Autowire成员是不可能的。

如果将bean设置为托管的@Component,则Spring将创建实例,并且侦听器不会注册外部servlet。

你不可能两种方式..

一种解决方案是删除Spring注释并从Spring Application上下文中手动检索您的成员,并以这种方式设置您的成员。

  public class InitApp implements ServletContextListener { private ConfigrationService weatherConfService; private static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:web-context.xml"); @Override public void contextInitialized(ServletContextEvent servletContextEvent) { weatherConfService = applicationContext.getBean(ConfigrationService.class); System.out.println(weatherConfService); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } } 
 @WebListener public class StartupListener implements ServletContextListener { @Autowired private MyRepository repository; @Override public void contextDestroyed(ServletContextEvent event) { } @Override public void contextInitialized(ServletContextEvent event) { AutowireCapableBeanFactory autowireCapableBeanFactory = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()).getAutowireCapableBeanFactory(); autowireCapableBeanFactory.autowireBean(this); repository.doSomething(); } }