監(jiān)聽器獲取Spring配置文件的方法
我們?cè)谧鲰?xiàng)目的時(shí)候,會(huì)用到監(jiān)聽器去獲取Spring的配置文件,然后從中拿出我們需要的bean出來,比如做網(wǎng)站首頁,假設(shè)商品的后臺(tái)業(yè)務(wù)邏輯都做好了,我們需要?jiǎng)?chuàng)建一個(gè)監(jiān)聽器,在項(xiàng)目啟動(dòng)時(shí)將首頁的數(shù)據(jù)查詢出來放到application里,即在監(jiān)聽器里調(diào)用后臺(tái)商品業(yè)務(wù)邏輯的方法,也就是說我們需要在監(jiān)聽器里獲取Spring中配置的相應(yīng)的bean。先把監(jiān)聽器創(chuàng)建出來:
1. 創(chuàng)建InitDataListener
創(chuàng)建一個(gè)監(jiān)聽器InitDataListener繼承ServletContextListener:
/** * @Description: TODO(用于項(xiàng)目啟動(dòng)的時(shí)候數(shù)據(jù)初始化) * @author eson_15 * */ //@Component //監(jiān)聽器是web層的組件,它是tomcat實(shí)例化的,不是Spring實(shí)例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null;//productService中定義了跟商品相關(guān)的業(yè)務(wù)邏輯 @Override public void contextDestroyed(ServletContextEvent event) { } @Override public void contextInitialized(ServletContextEvent event) { } }
并在web.xml中配置該監(jiān)聽器:
如上,productService中定義了商品的一些業(yè)務(wù)邏輯,并且這個(gè)productService是交給Spring管理的,那么我們?nèi)绾蔚玫竭@個(gè)對(duì)象呢?首先肯定的一點(diǎn)是:我們不能自己new出來,因?yàn)閚ew出來的話就跟Spring的IoC沒有關(guān)系了……主要有三種方式可以實(shí)現(xiàn),我們先一個(gè)個(gè)分析,最后比較優(yōu)劣。
2. 直接加載beans.xml文件
這種方式比較簡(jiǎn)單粗暴,不是要加載配置文件么?那好,我加載就是了,如下:
//@Component //監(jiān)聽器是web層的組件,它是tomcat實(shí)例化的,不是Spring實(shí)例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null; //productService中定義了跟商品相關(guān)的業(yè)務(wù)邏輯 @Override public void contextDestroyed(ServletContextEvent event) { } @Override public void contextInitialized(ServletContextEvent event) { // 獲取業(yè)務(wù)邏輯類productService查詢商品信息 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); productService = (ProductService) context.getBean("productService"); System.out.println(productService); //輸出看看拿到了沒有 //下面是具體productService相關(guān)操作…… } }
這種方法完全沒問題,思路很清晰,先加載配置文件beans.xml,然后獲取bean,但是啟動(dòng)tomcat后,我們看看控制臺(tái)輸出的信息:
到這里應(yīng)該發(fā)現(xiàn)這種方式的弊端了,加載了兩次配置文件,也就是說那些bean被實(shí)例化了兩次,從打印的信息來看,是拿到我們自己加載配置文件是實(shí)例化的bean。這種方式明顯不可取。
3. 從ServletContext中獲取
從上面的方法中,我們最起碼可以知道,Spring通過自己的監(jiān)聽器已經(jīng)加載過一次配置文件了,我們沒必要再加載一次,那么很容易想到,如果知道Spring加載后放到哪里了,那我們就可以從那地方獲取該配置文件,下面我們看下Spring加載配置文件的過程:
上圖中(省略了無關(guān)的代碼),ContextLoaderListener就是web.xml中我們配置的Spring監(jiān)聽器,它也實(shí)現(xiàn)了ServletContextListener并繼承了ContextLoader。在監(jiān)聽器中主要通過initWebApplicationContext方法來獲取配置文件,并創(chuàng)建WebApplicationContext對(duì)象,在initWebApplicationContext方法里主要做兩件事:一是拿到Spring的上下文,二是把Spring上下文放到ServletContext中,并且鍵為:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。那么如何拿到Spring的上下文呢?是通過獲取web.xml中配置的Spring的路徑,CONFIG_LOCATION_PARM其實(shí)是個(gè)字符串常量,就是上面web.xml中配置Spring監(jiān)聽器下面的:
<context-param> <param-name>contextConfigLocation</param-name> <!--CONFIG_LOCATION_PARM就是contextConfigLocation--> <param-value>classpath:beans.xml</param-value> </context-param>
所以就很明顯了,通過web.xml中配置的路徑拿到beans.xml,然后加載這個(gè)配置文件,實(shí)例化bean。
現(xiàn)在我們既然知道了Spring在加載配置文件后,把它放在了ServletContext中,那么我們就可以去這里面直接拿!
//@Component //監(jiān)聽器是web層的組件,它是tomcat實(shí)例化的,不是Spring實(shí)例化的。不能放到Spring中 public class InitDataListener implements ServletContextListener { private ProductService productService = null; @Override public void contextDestroyed(ServletContextEvent event) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent event) { // 獲取業(yè)務(wù)邏輯類查詢商品信息 // 解決方案二,項(xiàng)目在啟動(dòng)時(shí),把Spring配置文件通過Spring的監(jiān)聽器加載,存儲(chǔ)到ServletContext中,我們只要在ServletContext中獲取即可。 ApplicationContext context = (ApplicationContext) event.getServletContext() .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); productService = (ProductService) context.getBean("productService"); System.out.println(productService); } }
這樣我們就可以拿到produceService的實(shí)例化對(duì)象了,這種方法好是好,就是getAttribute中的參數(shù)太長(zhǎng),也不知道當(dāng)時(shí)程序員的腦門子被夾了還是咋地,估計(jì)是想不到其他更合適的名字了吧~
4. 通過Spring提供的工具類加載
也許開發(fā)Spring的大牛們也意識(shí)到了這個(gè)參數(shù)名字太長(zhǎng)了,于是他們提供了一個(gè)方法類,可以加載配置文件:
public class InitDataListener implements ServletContextListener { private ProductService productService = null; @Override public void contextDestroyed(ServletContextEvent event) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent event) { // 獲取業(yè)務(wù)邏輯類查詢商品信息 WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); productService = (ProductService) context.getBean("productService"); System.out.println(productService); } }
其實(shí),這里的getWebApplicationContext方法就是把上面的那個(gè)方法封裝了一下而已,我們看看這個(gè)方法的源碼就知道了:
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); }
這樣更加方便程序員調(diào)用,僅此而已……所以一般我們使用第三種方法來獲取Spring的配置文件,從而獲取相應(yīng)的實(shí)例化bean。
原文鏈接:http://blog.csdn.net/eson_15/article/details/51373937
以上就是iPhone6splus微信閃退的解決方法,希望對(duì)大家有所幫助,也希望大家多多支持腳本之家,關(guān)注腳本之家的更多精彩內(nèi)容。
- Spring boot通過HttpSessionListener監(jiān)聽器統(tǒng)計(jì)在線人數(shù)的實(shí)現(xiàn)代碼
- springboot 用監(jiān)聽器統(tǒng)計(jì)在線人數(shù)案例分析
- 在spring中使用自定義注解注冊(cè)監(jiān)聽器的方法
- Spring Boot的listener(監(jiān)聽器)簡(jiǎn)單使用實(shí)例詳解
- SpringBoot定義過濾器、監(jiān)聽器、攔截器的方法
- Spring Boot中配置定時(shí)任務(wù)、線程池與多線程池執(zhí)行的方法
- springboot schedule 解決定時(shí)任務(wù)不執(zhí)行的問題
- spring-boot 多線程并發(fā)定時(shí)任務(wù)的解決方案
- Spring監(jiān)聽器及定時(shí)任務(wù)實(shí)現(xiàn)方法詳解
相關(guān)文章
SpringBoot 如何添加容器啟動(dòng)的初始化邏輯的操作方法
這篇文章主要介紹了SpringBoot 如何添加容器啟動(dòng)的初始化邏輯,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09Spring Boot 配置 IDEA和DevTools 熱部署的方法
這篇文章主要介紹了Spring Boot 配置 IDEA和DevTools 熱部署的方法,需要的朋友可以參考下2018-02-02javaWeb實(shí)現(xiàn)簡(jiǎn)單文件上傳
這篇文章主要為大家詳細(xì)介紹了JAVAWeb實(shí)現(xiàn)簡(jiǎn)單文件上傳,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06