1.嵌入式Servlet容器自动配置原理
1.1 在spring-boot-autoconfigure-1.5.9.RELEASE.jar => springboot自动配置依赖 jar包下,EmbeddedServletContainerAutoConfiguration => 嵌入式servlet容器自动配置类
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication //如果是web应用,当前配置类生效 @Import(BeanPostProcessorsRegistrar.class) //Bean后置处理器的注册器;给容器中注入一些组件//导入了EmbeddedServletContainerCustomizerBeanPostProcessor//后置处理器功能:在bean初始化前后(刚创建完对象,还没属性赋值)执行初始化工作 public class EmbeddedServletContainerAutoConfiguration { /** * Nested configuration if Tomcat is being used. */ @Configuration @ConditionalOnClass({ Servlet.class, Tomcat.class }) //判断当前是否引入了Tomcat依赖; @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT) //判断当前容器没有用户自定义的EmbeddedServletContainerFactory(嵌入式servlet容器工厂);作用:创建servlet容器; public static class EmbeddedTomcat { @Bean public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() { return new TomcatEmbeddedServletContainerFactory(); } }
1.2 EmbeddedServletContainerFactory(嵌入式servlet容器工厂)
public interface EmbeddedServletContainerFactory { //获取嵌入式servlet容器 EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... var1); }
1.3 EmbeddedServletContainer(嵌入式servlet容器)
1.4 以TomcatEmbeddedServletContainerFactory为例
@Override public EmbeddedServletContainer getEmbeddedServletContainer( ServletContextInitializer... initializers) { // 创建Tomcat Tomcat tomcat = new Tomcat(); //配置Tomcat的基本环境 File baseDir = (this.baseDirectory != null ? this.baseDirectory : createTempDir("tomcat")); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); 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); //将配置好的Tomcat传入进去。返回一个EmbeddedServletContainer 并且启动tomcat容器 return getTomcatEmbeddedServletContainer(tomcat); }
1.4.1 我们对server的修改是怎么生效的呢?
ServerPorperties ,EmbeddedServletContainerCustomizer
EmbeddedServletContainerCustomizer帮我们修改了server配置,修改的原理是:
容器中也导入了EmbeddedServletContainerCustomizerBeanPostProcessor
//初始化之前 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //如果当前初始化的是一个ConfigurableEmbeddedServletContainer类型的组件 if (bean instanceof ConfigurableEmbeddedServletContainer) { postProcessBeforeInitialization((ConfigurableEmbeddedServletContainer) bean); } return bean; }
private void postProcessBeforeInitialization( ConfigurableEmbeddedServletContainer bean) { //获取所有的定制器,调用每一个定制器的customize()方法来给servlet容器进行属性赋值 for (EmbeddedServletContainerCustomizer customizer : getCustomizers()) { customizer.customize(bean); }}private Collection<EmbeddedServletContainerCustomizer> getCustomizers() {
if (this.customizers == null) { // Look up does not include the parent context this.customizers = new ArrayList<EmbeddedServletContainerCustomizer>( this.beanFactory //从容器中获取所有这个类型的组件:EmbeddedServletContainerCustomizer //如果要定制一个servlet容器,向容器中添加一个EmbeddedServletContainerCustomizer组件 .getBeansOfType(EmbeddedServletContainerCustomizer.class, false, false) .values()); Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE); this.customizers = Collections.unmodifiableList(this.customizers); } return this.customizers;}
2.嵌入式Servlet容器启动原理
2.1 获取嵌入式servlet容器工厂
2.1.1 springboot启动应用运行run方法
2.1.2 refreshContext(context);springboot刷新ioc容器【创建ioc容器对象,并初始化容器,创建容器中的每一个组件】;如果是web应用创建AnnotationConfigEmbeddedWebApplicationContext容器,否则创建默认的AnnotationConfigApplicationContext容器
2.1.3 refresh(context);刷新刚才创建好的ioc容器;
public void refresh() throws BeansException, IllegalStateException { Object var1 = this.startupShutdownMonitor; synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } }
2.1.4 onRefresh(); web的ioc容器重写了onRefresh()方法;
2.1.5 web ioc容器创建嵌入式servlet容器: createEmbeddedServletContainer();
2.1.6 获取嵌入式servlet容器工厂 getEmbeddedServletContainerFactory() =>从容器中获取EmbeddedServletContainerFactory组件
TomcatEmbeddedServletContainerFactory创建对象,后置处理器一看是这个对象,就获取所有的定制器,先定制servlet容器的相关配置
2.1.7 使用容器工厂获取嵌入式servlet容器 this.embeddedServletContainer = containerFactory.getEmbeddedServletContainer(getSelfInitializer());
2.1.8 嵌入式servlet容器创建对象并启动ioc容器;
先启动嵌入式servlet容器,再将ioc容器中没有创建的对象获取出来;ioc容器启动的时候创建嵌入式servlet容器。
原文地址:https://www.cnblogs.com/hlkawa/p/9736226.html