docs/Spring全家桶/SpringBoot源码解析/SpringBoot启动流程(四):启动IOC容器.md
һƪܽ springboot £
ģǼIJ衣
SpringApplication#refreshContext
private void refreshContext(ConfigurableApplicationContext context) {
// spring
refresh(context);
if (this.registerShutdownHook) {
try {
// ע ShutdownHook
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
refresh(context) spring Ҳǵ AbstractApplicationContext#refreshcontext.registerShutdownHook()ע ShutdownHook jvm ̹رʱһЩضIJSpringApplication#refresh
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
// spring
((AbstractApplicationContext) applicationContext).refresh();
}
ܼж applicationContext ǷΪ AbstractApplicationContextȻٵ AbstractApplicationContext#refresh()
AbstractApplicationContext#refresh()ǿǴ÷ spring ̡ڱIJǷ spring £ͲչˣҪ˽̵СԲο£
AbstractApplicationContext#refresh() Уspring ṩ˼չ㣺
ǵǰʹõ applicationContext Ϊ AnnotationConfigServletWebServerApplicationContextҲʹЩչ㣬ҪעЩչӦá
prepareRefresh()Է֣initPropertySources() е£
AbstractApplicationContext#refresh
|- AnnotationConfigServletWebServerApplicationContext#prepareRefresh
|- AbstractApplicationContext#prepareRefresh
|- GenericWebApplicationContext#initPropertySources
յõ GenericWebApplicationContext#initPropertySources
protected void initPropertySources() {
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
}
}
Ȼȡ EnvironmentȻжǷΪ ConfigurableWebEnvironment ʵǰʱʱǵõ Environment Ϊ StandardServletEnvironment ConfigurableWebEnvironment ķϣȻ ConfigurableWebEnvironment#initPropertySources StandardServletEnvironment#initPropertySources
public void initPropertySources(@Nullable ServletContext servletContext,
@Nullable ServletConfigservletConfig) {
// 滻õ servletContextInitParams Ϊ servletContext
// 滻õ servletConfigInitParams Ϊ servletConfig
WebApplicationContextUtils.initServletPropertySources(getPropertySources(),
servletContext, servletConfig);
}
Ǻֻܼǽ servletContext servletConfig õ Environment С
beanFactory: obtainFreshBeanFactory()ǰ applicationContext Ը÷չ
beanFactory: prepareBeanFactory(beanFactory)ǰ applicationContext Ը÷չ
postProcessBeanFactory(beanFactory)AnnotationConfigServletWebServerApplicationContext д
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// øķ
super.postProcessBeanFactory(beanFactory);
// аɨ裬İ
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
// עbeanΪ
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
ִй£
super.postProcessBeanFactory(beanFactory)basePackages Ϊ nulannotatedClasses annotatedClasses ΪҪ super.postProcessBeanFactory(beanFactory)÷ ServletWebServerApplicationContext У
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// һ BeanPostProcessor
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
// ServletContextAware Զע
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
// ע web bean ķΧעrequestsessionglobalSession
registerWebApplicationScopes();
}
ݱȽϼҪע BeanPostProcessor Լע web bean ÷ΧҪ WebApplicationContextServletContextAwareProcessor ã£
public class WebApplicationContextServletContextAwareProcessor
extends ServletContextAwareProcessor {
private final ConfigurableWebApplicationContext webApplicationContext;
public WebApplicationContextServletContextAwareProcessor(
ConfigurableWebApplicationContext webApplicationContext) {
Assert.notNull(webApplicationContext, "WebApplicationContext must not be null");
this.webApplicationContext = webApplicationContext;
}
/**
* ȡ ServletContext
*/
@Override
protected ServletContext getServletContext() {
ServletContext servletContext = this.webApplicationContext.getServletContext();
return (servletContext != null) ? servletContext : super.getServletContext();
}
/**
* ȡ ServletConfig
*/
@Override
protected ServletConfig getServletConfig() {
ServletConfig servletConfig = this.webApplicationContext.getServletConfig();
return (servletConfig != null) ? servletConfig : super.getServletConfig();
}
}
ƺûʲôٸ࣬Ǹ BeanPostProcessorҪע postProcessBeforeInitialization() postProcessAfterInitialization()
public class ServletContextAwareProcessor implements BeanPostProcessor {
...
public Object postProcessBeforeInitialization(Object bean,
String beanName) throws BeansException {
// ServletContext
if (getServletContext() != null && bean instanceof ServletContextAware) {
((ServletContextAware) bean).setServletContext(getServletContext());
}
// ServletConfig
if (getServletConfig() != null && bean instanceof ServletConfigAware) {
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
Կ BeanPostProcessor ServletContextAware ServletConfigAware Aware ӿڵģ·ͬ ApplicationAware``BeanFactoryAware һ
BeanFactoryPostProcessors: invokeBeanFactoryPostProcessors(beanFactory)ǰ applicationContext Ը÷չ
ֵһǣУиص BeanFactoryPostProcessor ᱻִУConfigurationClassPostProcessorspringboot Զװע @EnableAutoConfiguration ﴦԶװļءעҲ ConfigurationClassPostProcessor С
BeanPostProcessor: registerBeanPostProcessors(beanFactory)ǰ applicationContext Ը÷չ
MessageSource(ڹʻ): initMessageSource()ǰ applicationContext Ը÷չ
initApplicationEventMulticaster()ǰ applicationContext Ը÷չ
onRefresh()ǰ applicationContext Ը÷չΪ ServletWebServerApplicationContext#onRefresh £
@Override
protected void onRefresh() {
// ø
super.onRefresh();
try {
// webtomcat,jetty
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException(...);
}
}
web дġ web ĴҪжϣǺϸ˵
registerListeners()ǰ applicationContext Ը÷չ
bean: finishBeanFactoryInitialization(beanFactory)ǰ applicationContext Ը÷չ
finishRefresh()ǰ applicationContext Ը÷չΪ ServletWebServerApplicationContext#finishRefresh £
@Override
protected void finishRefresh() {
super.finishRefresh();
// web
WebServer webServer = startWebServer();
if (webServer != null) {
// ServletWebServerInitializedEvent ¼
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
/**
* web
*/
private WebServer startWebServer() {
WebServer webServer = this.webServer;
if (webServer != null) {
webServer.start();
}
return webServer;
}
Կ web
resetCommonCaches()ǰ applicationContext Ը÷չ
ShutdownHookcontext.registerShutdownHook()÷ AbstractApplicationContext#registerShutdownHook ṩ
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
...
@Override
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// ̵ָ߳
this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
// ShutdownHook
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
/**
* Ĺرղ
*/
protected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
LiveBeansView.unregisterApplicationContext(this);
try {
// ر¼
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn(...);
}
// lifecycle onClose()
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
}
catch (Throwable ex) {
logger.warn(...);
}
}
// bean
destroyBeans();
// ر
closeBeanFactory();
// չ㣬ʵ
onClose();
//
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// active ʶ
this.active.set(false);
}
}
...
}
Կcontext.registerShutdownHook() ʵ doClose() Ĺرղر spring ĹرգעѾ൱ˣͲˡ
ˣͷˣ spring չ onRefresh() finishRefresh()ǰߴ webServer webServer
ԭӣhttps://my.oschina.net/funcy/blog/4888129 ߸ˮƽд֮ӭָԭףҵתϵȨҵתע