传统的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