先说结论,百度上这个问题真的好难查,终于找到一个解决方法
https://blog.csdn.net/u014723529/article/details/51404187
类似文章还有http://kewen1989.iteye.com/blog/1891124
正文
公司项目,之前是用spring,后来要移植到spring boot
项目中有一个通过ApplicatonContextAware获取spring上下文的类
@Component
public class SpringContextHolder implements ApplicationContextAware {
private static ApplicationContext ctx = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ctx = applicationContext;
}
public static ApplicationContext getSpringContext(){
return ctx;
}
}
还有一个ServletContextListener,在AListener中使用SpringContextHolder获取ApplicationContext,从而去getBean
@Component
public class AListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce) {
SpringContextHolder.getSpringContext.getBean("TestBean");
}
public void contextInitialized(ServletContextEvent sce) {}
}
原spring项目中web.xml配置如下
<!-- 设置Spring监听器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml, classpath:applicationContext-* </param-value> </context-param> <listener> <listener-class>........AListener</listener-class> </listener>
按web.xml配置顺序应该是先加载ContextLoaderListener,此时spring会自动去调用SpringContextHolder的setApplicationContext方法。随后调用AListener
但是移植到spring boot之后,通过@ServletComponentScan,或者在入口函数下面通过@Bean向spring注册bean,都会先加载AListener后在SpringContextHolder中设置上下文
debug了一下源码,在AbstractApplicationContext.java中refresh()中registerListeners()会启动内置tomcat容器,启动tomcat时会初始化AListener,然后在finishBeanFactoryInitialization(beanFactory)为SpringContextAware设置上下文。
所以难道这个顺序在spring boot里面是死的吗?spring+tomcat是tomcat容器去加载spring,spring boot好像是spring boot框架去加载tomcat
暂时这个问题还要再研究
不过倒是找到了在AListener中获取SpringContext的方法,即文章开头链接中的方法
public void contextInitialized(ServletContextEvent event) {
app = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
app.getBean("UserService");
}