通过之前的学习我们大致上已经知道了SpringBoot启动的流程。到目前剩下的就是如何将BeanDefineMap中的类转化为真实的bean,然后注册到beanFactory的beanMap中了。那么onRefresh方法是否就是做这件事情的?
protected void onRefresh() {
super.onRefresh();
try {
this.createWebServer();
} catch (Throwable var2) {
throw new ApplicationContextException("Unable to start web server", var2);
}
}
我们看到在GenericWebApplicationContext中调用了
UiApplicationContextUtils.initThemeSource(this);方法。继续跟踪,我们进入initThemeSource这个方法。
public static ThemeSource initThemeSource(ApplicationContext context) {
if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) {
//themeSource是否存在,不存在的时候创建,这里的getBean方法是关键
ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class);
// Make ThemeSource aware of parent ThemeSource.
if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
if (hts.getParentThemeSource() == null) {
// Only set parent context as parent ThemeSource if no parent ThemeSource
// registered already.
hts.setParentThemeSource((ThemeSource) context.getParent());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using ThemeSource [" + themeSource + "]");
}
return themeSource;
}
else {
//创建themeSource对象并返回。
// Use default ThemeSource to be able to accept getTheme calls, either
// delegating to parent context's default or to local ResourceBundleThemeSource.
HierarchicalThemeSource themeSource = null;
if (context.getParent() instanceof ThemeSource) {
themeSource = new DelegatingThemeSource();
themeSource.setParentThemeSource((ThemeSource) context.getParent());
}
else {
themeSource = new ResourceBundleThemeSource();
}
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME +
"': using default [" + themeSource + "]");
}
return themeSource;
}
}
//创建web服务
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = this.getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = this.getWebServerFactory();
this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()});
} else if (servletContext != null) {
try {
this.getSelfInitializer().onStartup(servletContext);
} catch (ServletException var4) {
throw new ApplicationContextException("Cannot initialize servlet context", var4);
}
}
this.initPropertySources();
}
这块是获取tomcat的,通过ServletWebServerFactory拿取servlet服务器
protected ServletWebServerFactory getWebServerFactory() {
String[] beanNames = this.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");
} else if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
} else {
return (ServletWebServerFactory)this.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
}
代码运行到这里的时候,tomcat已经加载好了。
protected void initPropertySources() {
ConfigurableEnvironment env = this.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null);
}
}
又进行了一次配置修改
public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
}
创建完servlet服务器之后,就开始注册registerListener。这块就是上篇文档我们说到的ApplicationListenner接口。
执行完上述操作之后,我们看看finishBeanFactoryInitialization是做那些工作的。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
通过debug发现,这个方法对bean进行实例化。
通过这个方法之后,singletonObjects被逐渐转化为bean实体。
在finishRefresh方法中
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// 初始化一个处理器initLifecycleProcessor();
// 拿到处理器,并初始化lifecycle接口的类 getLifecycleProcessor().onRefresh();
// 发布容器已经刷新的消息
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
初始化有lifecycle接口的类
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
// 这里开始调用lifecycle接口bean的方法
private void startBeans(boolean autoStartupOnly) {
//获取实现了lifecycle接口的bean
Map, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map, LifecycleGroup> phases = new HashMap<>();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
Listkeys =new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
但是分析到这里就比较奇特了,这里只是启动启动了tomcat,那么tomcat是在哪里创建的?
我跟踪代码.
我们发现在OnRefresh方法中就创建了。我们看到OnRefresh方法有4个实现。
我们依次查看源代码,看看实现有什么差别。发现ServletWebServerApplicationContent和ReactiveWebServerApplicationContent都有Servlet容器服务的创建。
在这里突然想到,如果我们不做服务端也就是不想启动servlet容器,那么是不是就不用用剩余的两个content类?如果是这样的话,那么肯定在创建这里的content时候就决定了。我们知道当时创建content容器的时候得方法是createApplicationContent方法。
那么是不是我们设置了webApplicationType就可以了?通过研究发现确实是这样的。其实我一直觉得控制是否启动servlet容器的控制在于OnRefresh中,现在发现spring调用前就决定了一切。
SpringApplicationBuilder builder = new SpringApplicationBuilder(MergeeServic.class);
ApplicationContext applicationContext = builder.web(WebApplicationType.NONE).headless(false).run(args);
通过上述分析,springboot的过程已经解析的基本明确了。