四,分析Spring Boot底层机制(Tomcat 启动分析+Spring容器初始化+Tomcat如何关联 Spring 容器) 以及个人编写启动 Tomcat
@
目录
1. 源码分析 Spring Boot是如何启动 Tomcat ,并支持访问 @Controller 的 Debug 流程分析
进行源码分析,天然是少不了,Debug 的。下面就让我们打上断点 ,Debug起来吧
1.1 源码分析: SpringApplication.run( ) 方法
- SpringApplication.run()
- DeBug SpringApplication.run(MainApp.class, args); 看看 Spring Boot 是如何启动 Tomcat的
复制代码我们的Debug 目的:紧抓一条线,就是看到 tomcat 被启动的代码: 好比 tomcat.start()
- // 这里我们开始 Debug SpringApplication。run()
- public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
- return run(new Class[]{primarySource}, args);
- }
复制代码- public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
- return (new SpringApplication(primarySources)).run(args);
- }
复制代码 3.SpringApplication.java

 - public ConfigurableApplicationContext run(String... args) {
- StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
- ConfigurableApplicationContext context = null;
- this.configureHeadlessProperty();
- SpringApplicationRunListeners listeners = this.getRunListeners(args);
- listeners.starting(bootstrapContext, this.mainApplicationClass);
- try {
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
- this.configureIgnoreBeanInfo(environment);
- Banner printedBanner = this.printBanner(environment);
- context = this.createApplicationContext(); // 特别分析: 创建容器
- context.setApplicationStartup(this.applicationStartup);
- this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- this.refreshContext(context); // 特别分析:刷新应用程序上下文,比如:初始化默认设置/注入相关Bean/启动 tomcat
- this.afterRefresh(context, applicationArguments);
- stopWatch.stop();
- if (this.logStartupInfo) {
- (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
- }
- listeners.started(context);
- this.callRunners(context, applicationArguments);
- } catch (Throwable var10) {
- this.handleRunFailure(context, var10, listeners);
- throw new IllegalStateException(var10);
- }
- try {
- listeners.running(context);
- return context;
- } catch (Throwable var9) {
- this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
- throw new IllegalStateException(var9);
- }
- }
复制代码
- SpringApplication.java : 容器类型很多,会根据你的 this.webApplicationType 创建对应的容器
默认 this.webApplicationType 是 servlet 也就是 web 容器/处置惩罚的 servlet
- protected ConfigurableApplicationContext createApplicationContext() {
- return this.applicationContextFactory.create(this.webApplicationType);
- }
复制代码
- ApplicationContextFactory.java
默认是进入这个分支 case SERVLET: 返回 new AnnotationConfigServletWebServerApplicationContext();
 - public interface ApplicationContextFactory {
- ApplicationContextFactory DEFAULT = (webApplicationType) -> {
- try {
- switch(webApplicationType) {
- case SERVLET: // 默认是进入这个分支
- return new AnnotationConfigServletWebServerApplicationContext();
- case REACTIVE:
- return new AnnotationConfigReactiveWebServerApplicationContext();
- default:
- return new AnnotationConfigApplicationContext();
- }
- } catch (Exception var2) {
- throw new IllegalStateException("Unable create a default ApplicationContext instance, you may need a custom ApplicationContextFactory", var2);
- }
- };
- ConfigurableApplicationContext create(WebApplicationType webApplicationType);
- static ApplicationContextFactory ofContextClass(Class<? extends ConfigurableApplicationContext> contextClass) {
- return of(() -> {
- return (ConfigurableApplicationContext)BeanUtils.instantiateClass(contextClass);
- });
- }
- static ApplicationContextFactory of(Supplier<ConfigurableApplicationContext> supplier) {
- return (webApplicationType) -> {
- return (ConfigurableApplicationContext)supplier.get();
- };
- }
- }
复制代码 2.1 实现任务阶段1:创建Tomcat 并启动
- private void refreshContext(ConfigurableApplicationContext context) {
- if (this.registerShutdownHook) {
- shutdownHook.registerApplicationContext(context);
- }
- this.refresh(context); // 特别分析,真正执行相关任务
- }
复制代码 2.2 实现任务阶段2:创建Spring容器
bean 对象。
- protected void refresh(ConfigurableApplicationContext applicationContext) {
- applicationContext.refresh();
- }
复制代码 bean 对象对应的 config 配置类
- public final void refresh() throws BeansException, IllegalStateException {
- try {
- super.refresh(); // 特别分析这个方法
- } catch (RuntimeException var3) {
- WebServer webServer = this.webServer;
- if (webServer != null) {
- webServer.stop();
- }
- throw var3;
- }
- }
复制代码 controller 处置惩罚业务哀求的控制器
 - public void refresh() throws BeansException, IllegalStateException {
- synchronized(this.startupShutdownMonitor) {
- StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
- this.prepareRefresh();
- ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
- this.prepareBeanFactory(beanFactory);
- try {
- this.postProcessBeanFactory(beanFactory);
- StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
- this.invokeBeanFactoryPostProcessors(beanFactory);
- this.registerBeanPostProcessors(beanFactory);
- beanPostProcess.end();
- this.initMessageSource();
- this.initApplicationEventMulticaster();
- this.onRefresh(); // 特别分析,当父类完成通用的工作后,再重新动态绑定机制回到
- this.registerListeners();
- this.finishBeanFactoryInitialization(beanFactory);
- this.finishRefresh();
- } catch (BeansException var10) {
- if (this.logger.isWarnEnabled()) {
- this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
- }
- this.destroyBeans();
- this.cancelRefresh(var10);
- throw var10;
- } finally {
- this.resetCommonCaches();
- contextRefresh.end();
- }
- }
- }
复制代码 2.3 实现任务阶段3:将Tomcat 和 Spring 容器关联,并启动Spring容器
- protected void onRefresh() {
- super.onRefresh();
- try {
- this.createWebServer(); 创建 webServer 可以理解成会创建指定 web服务器-tomcat
- } catch (Throwable var2) {
- throw new ApplicationContextException("Unable to start web server", var2);
- }
- }
复制代码 - private void createWebServer() {
- WebServer webServer = this.webServer;
- ServletContext servletContext = this.getServletContext();
- if (webServer == null && servletContext == null) {
- StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
- ServletWebServerFactory factory = this.getWebServerFactory();
- createWebServer.tag("factory", factory.getClass().toString());
- this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer
- ()}); // 特别分析,使用 TomcatServletWebServerFactory 创建一个TomcatWEbServer
- createWebServer.end();
- this.getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer));
- this.getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer));
- } else if (servletContext != null) {
- try {
- this.getSelfInitializer().onStartup(servletContext);
- } catch (ServletException var5) {
- throw new ApplicationContextException("Cannot initialize servlet context", var5);
- }
- }
- this.initPropertySources();
- }
复制代码 3. 末了:
“在这个末了的篇章中,我要表达我对每一位读者的感激之情。你们的关注和复兴是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继承在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |