SpringBoot啓動ServletContextListener獲取SpringContext

背景

傳統的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

springBoot改造方案

經過使用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 Blogide

相關文章
相關標籤/搜索