如何在servlet的監聽器中使用spring容器的bean


 

另外補充下:在web Server容器中,無論是Servlet,Filter,還是Listener都不是Spring容器管理的,因此我們都無法在這些類中直接使用Spring注解的方式來注入我們需要的對象,當然除了下面我們詳細說的方法外,還有的比如說為了在Servlet中使用Spring容器的對象,那么可以參考如下兩篇文章:

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

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

額外文章就參考這么多

 

以下是原文:

1.在java web項目中我們通常會有這樣的需求:

當項目啟動時執行一些初始化操作,例如從數據庫加載全局配置文件等,通常情況下我們會用javaee規范中的Listener去實現

例如

復制代碼
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的生命周期。

(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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM