傳統的tomcat方式運行的項目改造SpringBoot方式,遇到listener和springContext加載的關係問題。java
傳統項目配置listener方式在web.xml中,tomcat啓動是會檢查web.xml文件進行加載,以下:web
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>com.tx.MonitoerLoaderListener</listener-class> </listener>
在項目中通常都會寫個靜態的公共類SpringContextHolder來獲取bean,以下:spring
public class SpringContextHolder implements ApplicationContextAware{ private static ApplicationContext applicationContext = null; @Override public void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; } public static <T> T getBean(String name) { assertContextInjected(); return (T) applicationContext.getBean(name); } public static <T> T getBean(Class<T> requiredType) { assertContextInjected(); return applicationContext.getBean(requiredType); } }
在tomcat啓動時會掃描並調用實現了ApplicationContextAware接口的setApplicationContext方法從而設置SpringContextHolder。這個會在listener加載前先執行。因此listener中能夠直接使用傳遞SpringContextHolder的getBean(xx)方法。spring-mvc
項目改形成SpringBoot後,經過@ServletComponentScan註冊listener,每次都是先加載listener後加載ApplicationContextAware一直沒法獲取到SpringContext。tomcat
經過使用spring-web自帶的類WebApplicationContextUtils的getWebApplicationContext(ServletContext xx)會返回一個WebApplicationContext,以下:mvc
@WebListener public class BootServiceListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()); if(!SpringContextHolder.hasContext()) SpringContextHolder.setSpringContext(wac); }
配合@ServletComponentScan("xxx.xx.config")便可。app
做者:Owen Jia,推薦關注他的博客:Owen Blog 。ide