跟SpringBoot 源码分析刷新应用上下文(3)-refreshContext
这个篇文章一样的入口,一直到
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备刷新此上下文
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 准备bean工厂以便在此上下文中使用。
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 允许在上下文子类中对bean工厂进行后处理
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用在上下文中注册为bean的工厂处理器
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册拦截bean创建的bean处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化此上下文的消息源
initMessageSource();
// Initialize event multicaster for this context.
// 初始化此上下文的事件多播
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 初始化特定上下文子类中的其他特殊bean
onRefresh();
// Check for listener beans and register them.
// 检查侦听器bean并注册它们
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
// 实例化所有剩余的(非惰性init)singleton
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
// 最后一步:发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
// 销毁已创建的singleton以避免挂起资源
destroyBeans();
// Reset 'active' flag.
// 重置“活动”标志
cancelRefresh(ex);
// Propagate exception to caller.
// 向调用方传播异常
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// 重置Spring核心中的常见内省缓存,因为我们
// might not ever need metadata for singleton beans anymore...
// 可能不再需要单例bean的元数据了。。。
resetCommonCaches();
}
}
}
这里查看 onRefresh(); 方法
截图:
代码:
/**
* Template method which can be overridden to add context-specific refresh work.
* 可以重写以添加上下文特定刷新工作的模板方法。
* Called on initialization of special beans, before instantiation of singletons.
* 在初始化特殊 bean 时调用,在实例化 singleton 之前调用
* This implementation is empty. -- 此实现为空
* @throws BeansException in case of errors
* @see #refresh()
*/
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
找到其具体类的实现方法 ServeltWebServerApplicationContext
截图:
代码:
@Override
protected void onRefresh() {
super.onRefresh();
try {
// 核心方法,会获取嵌入的 Servlet 对象,并通过工厂获取 Servlet 容器
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
接着看其实现方法 createWebServer()
截图:
代码:
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
// 先获取 Servlet 容器工厂对象
ServletWebServerFactory factory = getWebServerFactory();
// getSelfInitializer() 这个方法在 完成 springMVC 的自动装配的时候会用到
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
接着看 红框中 this.webServer = factory.getWebServer(getSelfInitializer());方法
截图:
是一个接口,接着找到其具体实现类 TomcatServletWebServerFactory
截图:
代码:
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
//实例化一个 Tomcat
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
//设置 Tomcat 的工作临时目录
tomcat.setBaseDir(baseDir.getAbsolutePath());
// 进行 Tomcat 实例对象的各种配置信息
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
//个体 Service 添加 Connector
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
// 关闭热部署
tomcat.getHost().setAutoDeploy(false);
// 配置 Engine
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
// 实例化 TomcatWebServer 时会将 DespatcherServlet 以及一些 Filter 添加到 Tomcat 中
return getTomcatWebServer(tomcat);
}
接着看红框的方法 getTomcatWebServer(tomcat)
截图:
代码:
/**
* Factory method called to create the {@link TomcatWebServer}. Subclasses can
* override this method to return a different {@link TomcatWebServer} or apply
* additional processing to the Tomcat server.
* 为创建 TomcatWebServe 而调用的 Factory 方法。子类可以覆盖此方法以返回不同的 TomcatWebServe 或者 对 Tomcat 服务器应用额外的处理
* @param tomcat the Tomcat server.
* @return a new {@link TomcatWebServer} instance -- 一个新的 TomcatWebServe 实例
*/
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0);
}
接着查看 TomcatWebServer 的构造方法
代码:
/**
* Create a new {@link TomcatWebServer} instance.
* @param tomcat the underlying Tomcat server
* @param autoStart if the server should be started
*/
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
initialize();
}
接着看 initialize() 方法
截图:
代码:
private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
try {
addInstanceIdToEngineName();
Context context = findContext();
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// 删除服务连接器,这样协议绑定就不会
// happen when the service is started.
// 当服务启动时发生
removeServiceConnectors();
}
});
// Start the server to trigger initialization listeners
// 启动服务器以触发初始化侦听器
this.tomcat.start();
// We can re-throw failure exception directly in the main thread
// 我们可以直接在主线程中重新抛出失败异常
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
// 未启用命名。持续
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// 与Jetty不同,所有Tomcat线程都是守护进程线程。我们创建
// blocking non-daemon to stop immediate shutdown
// 阻止非后台进程以停止立即关闭
startDaemonAwaitThread();
}
catch (Exception ex) {
stopSilently();
destroySilently();
throw new WebServerException("Unable to start embedded Tomcat", ex);
}
}
}