Pytest學習(十九)- 報告Environment 不顯示怎麼辦
阿新 • • 發佈:2020-11-29
啟動內建Tomcat原理
從SpringApplication.run進入
/* SpringApplication > run() */ ...... try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); //建立web容器或者普通IOC容器 context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); //重新整理容器 refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } ......
從refreshContext進入,會一直調到AbstartApplicationContext的refresh()方法
/* AbstartApplicaionContext > refresh() */ ...... // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //註冊自定義的beanDefinition,並執行BeanFactory和BeanDefinition後置處理器方法 //這裡會BeanFactory的後置處理器方法,完成springBoot屬性自動注入 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //本來是一個空方法,但ServletWebServerApplicationContext實現了這個方法,並且在這裡完成對Tomcat的啟動 onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //對ben進行初始化 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); ......
進入onRefresh方法中
/*
ServletWebServerApplicaionContext > onRefresh()
*/
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
/* ServletWebServerApplicaionContext > createWebServer() */ private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null) { //獲取對應的webServer工廠,並呼叫自動裝配好的容器自定義定製器 ServletWebServerFactory factory = getWebServerFactory(); //獲取Tomcat物件 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(); }
進入getWebServer方法,完成對內建Tomcat建立和啟動
/*
TomcatServletWebServletFactory > getWebServer()
*/
@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());
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}
從getTomcatWebServer方法進去,最後呼叫initialize方法完成對Tomcat啟動
/*
TomcatWebServer > initialize()
*/
// Start the server to trigger initialization listeners
//啟動Tomcat
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
}