SpringBoot 2.x 外部servlet容器启动原理

SpringBoot 2.x 外部servlet容器启动原理

1)创建一个war项目,创建好目录结构(webapp文件夹,web.xml)
2)将嵌入式tomcat指定为provided

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

3)编写一个SpringBootServletInitializer 子类,并重写config方法

public class ServletInitializer extends SpringBootServletInitializer {
   
   //调用父类的 onStartup方法
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Springboot06WebJspApplication.class);
    }
}

4)启动服务器

1.原理:

首先启动servlet容器,servlet容器带动springBoot应用启动
  servlet3.0定义规则:
    1)服务器启动时,会创建当前web应用每一个jar包里的ServletContainerInitializer实例
    2)jar包的META-INF/service w文件夹下有一个
javax.servlet.ServletContainerInitialize 文件

文件的内容是 ServletContinerInitializer 实现类的全路径
    3)@HandlesTypes()能够在应用启动时加载我们想要加载的类

2.启动流程:
1) 启动tomcat
2) 创建ServletContainerInitializer 实例
  • org\springframework\spring-web\5.2.1.RELEASE\spring-web-5.2.1.RELEASE.jar!\META-INF\services\javax.servlet.ServletContainerInitializer
  • 创建 org.springframework.web.SpringServletContainerInitializer 实例
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w82vEmw1-1580790515045)(./QQ截图20200204113556.png)]
3) SpringServletContainerInitializer 上的 @HandlesType(WebApplicationInitializer.class) 将所有WebApplicationInitializer类型的实例以set集合的形式加载进来,并为其创建实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xWAI29W9-1580790515052)(./QQ截图20200204115600.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qeqi4Dzv-1580790515057)(./QQ截图20200204114723.png)]

4) 每一个WebApplicationInitializer 实例都会调用自己的 onStartup() 方法
  • 我们自己创建的 SpringBootServletInitializer 将会被实例化,并执行onStartup 方法
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oFTTpgcx-1580790515058)(./QQ截图20200204120240.png)]
5) SpringBootServletInitializer 实例执行 onStartup方法时 会执行createRootApplicationContext 方法创建容器
WebApplicationContext rootAppContext = createRootApplicationContext(servletContext);
6)createRootApplicationContext创建容器时会执行builder = configure(builder);方法
  • 因为子类重写了这个方法,会将springBoot主程序类传入
protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
      //因为子类重写了这个方法,会将springBoot主程序类传入
		builder = configure(builder);
		builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext));
		//使用bulid 创建一个spring应用
		SpringApplication application = builder.build();
		//启动springBoot应用
		return run(application);
	}
	
	//启动spring应用
	protected WebApplicationContext run(SpringApplication application) {
		return (WebApplicationContext) application.run();
	}
7)springBoot应用启动并创建IOC容器
  • refreshContext(context);刷新IOC容器
  • –>createWebServer();
  • –>ServletWebServerFactory factory = getWebServerFactory();
    –>this.webServer = factory.getWebServer(getSelfInitializer());
   	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//刷新IOC容器
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值