如何在自定義Listener(監聽器)中使用Spring容器管理的bean

正好之前項目中碰到這個問題,如今網上偶然又看到這個問題的博文,那就轉一下吧。html

原文:http://blog.lifw.org/post/46428852 感謝做者java

另外補充下:在web Server容器中,不管是Servlet,Filter,仍是Listener都不是Spring容器管理的,所以咱們都沒法在這些類中直接使用Spring註解的方式來注入咱們須要的對象,固然除了下面咱們詳細說的方法外,還有的好比說爲了在Servlet中使用Spring容器的對象,那麼能夠參考以下兩篇文章:web

Servlet自動注入Spring容器中的Bean解決方法spring

在servlet中注入spring的bean,servlet容器和spring容器數據庫

額外文章就參考這麼多tomcat

 

如下是原文:框架

1.在java web項目中咱們一般會有這樣的需求:當項目啓動時執行一些初始化操做,例如從數據庫加載全局配置文件等,一般狀況下咱們會用javaee規範中的Listener去實現,例如ide

1 public class ConfigListener implements ServletContextListener { 2  @Override 3 public void contextInitialized(ServletContextEvent sce) { 4 //執行初始化操做 5  } 6  @Override 7 public void contextDestroyed(ServletContextEvent sce) { 8  } 9 }

2.這樣當servlet容器初始化完成後便會調用contextInitialized方法。可是一般咱們在執行初始化的過程當中會調用service和dao層提供的方法,而如今web項目一般會採用spring框架來管理和裝配bean,咱們想固然會像下面這麼寫,假設執行初始化的過程當中須要調用ConfigService的initConfig方法,而ConfigService由spring容器管理(標有@Service註解)工具

public class ConfigListener implements ServletContextListener { @Autowired private ConfigService configService; @Override public void contextInitialized(ServletContextEvent sce) { configService.initConfig(); } @Override public void contextDestroyed(ServletContextEvent sce) { } }

3.然而以上代碼會在項目啓動時拋出空指針異常!ConfigService實例並無成功注入。這是爲何呢?要理解這個問題,首先要區分Listener的生命週期和spring管理的bean的生命週期。post

(1)Listener的生命週期是由servlet容器(例如tomcat)管理的,項目啓動時上例中的ConfigListener是由servlet容器實例化並調用其contextInitialized方法,而servlet容器並不認得@Autowired註解,所以致使ConfigService實例注入失敗。

(2)而spring容器中的bean的生命週期是由spring容器管理的。

4.那麼該如何在spring容器外面獲取到spring容器bean實例的引用呢?這就須要用到spring爲咱們提供的WebApplicationContextUtils工具類,該工具類的做用是獲取到spring容器的引用,進而獲取到咱們須要的bean實例。代碼以下

public class ConfigListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { ConfigService configService = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean(ConfigService.class); configService.initConfig(); } @Override public void contextDestroyed(ServletContextEvent sce) { } }

注意:以上代碼有一個前提,那就是servlet容器在實例化ConfigListener並調用其方法以前,要確保spring容器已經初始化完畢!而spring容器的初始化也是由Listener(ContextLoaderListener)完成,所以只需在web.xml中先配置初始化spring容器的Listener,而後在配置本身的Listener,配置以下

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>example.ConfigListener</listener-class> </listener>
相關文章
相關標籤/搜索