淘宝加盟网站建设,网站正能量大全,注册电子邮箱号,门户网站的建设要求目录 代码入口上下文容器 加载web容器WebServercreateWebServergetWebServerFactory()#xff1a;getWebServer(): 执行WebServer#start自动配置读取配置修改配置 代码入口
上下文容器
SpringApplication.run(App.class);
//追踪下去发现
context createApplicationContext… 目录 代码入口上下文容器 加载web容器WebServercreateWebServergetWebServerFactory()getWebServer(): 执行WebServer#start自动配置读取配置修改配置 代码入口
上下文容器
SpringApplication.run(App.class);
//追踪下去发现
context createApplicationContext();createApplicationContext()
return this.applicationContextFactory.create(this.webApplicationType);这里用了策略模式
读取 interface org.springframework.boot.ApplicationContextFactory 的实现
根据 webApplicationType 匹配对应的处理
case : WebApplicationType.REACTIVE : return new AnnotationConfigReactiveWebServerApplicationContext();
case : WebApplicationType.SERVLET : return new AnnotationConfigServletWebServerApplicationContext();然后就创建了
org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContextwebApplicationType 获取
//this.webApplicationType是在new SpringApplication()的时候赋值的
this.webApplicationType WebApplicationType.deduceFromClasspath();WebApplicationType.deduceFromClasspath():if (classpath中 有 org.springframework.web.reactive.DispatcherHandler
且 没有 org.springframework.web.servlet.DispatcherServlet
且 没有 org.glassfish.jersey.servlet.ServletContainer) {return WebApplicationType.REACTIVE;
}//有 spring-web的依赖则有
if (classpath中 没有 javax.servlet.Servlet) {return WebApplicationType.NONE;
}
if (classpath中 没有 org.springframework.web.context.ConfigurableWebApplicationContext) {return WebApplicationType.NONE;
}
return WebApplicationType.SERVLET;加载web容器
首先我们知道了现在的上下文是AnnotationConfigServletWebServerApplicationContext 看一下依赖
执行 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefreshorg.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer
来创建一个WebServerWebServer
我们先来分析下这个类 这个类是一个接口
void start() throws WebServerException;
void stop() throws WebServerException;
//返回监听端口
int getPort();
//优雅关闭
void shutDownGracefully(GracefulShutdownCallback callback);createWebServer
//看下容器中是否有webServer 这里是没有的
WebServer webServer this.webServer;
ServletContext servletContext this.servletContext;
if (webServer null servletContext null) {//获取WebServerFactory 这里会确定 web容器是 tomcat 还是其他ServletWebServerFactory factory getWebServerFactory();//这一步就初始化容器了 设置端口啥的//这里要注意了 getWebServer入参是ServletContextInitializer 这是一个函数类//也就是说只是设置了行为而不需要执行 先执行了getWebServerthis.webServer factory.getWebServer(getSelfInitializer());//注册优雅关闭getBeanFactory().registerSingleton(webServerGracefulShutdown,new WebServerGracefulShutdownLifecycle(this.webServer));//注册启动 关闭getBeanFactory().registerSingleton(webServerStartStop,new WebServerStartStopLifecycle(this, this.webServer));
}getWebServerFactory()
//获取Bean工厂里ServletWebServerFactory的BeanName
//这里获取的是 tomcatServletWebServerFactory
String[] beanNames getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
//这里会校验 容器中有且只能有一个ServletWebServerFactory类
if (beanNames.length 0) {throw new MissingWebServerFactoryBeanException()}
if (beanNames.length 1) {throw new ApplicationContextException()}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);为什么获取的是 tomcatServletWebServerFactory 呢
一般找不到在哪里注入的Bean的时候就可以试一下搜索XXXAutoConfiguration
就是利用自动配置类 SPI机制加载 ServletWebServerFactoryAutoConfiguration
其中引入了
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class
ServletWebServerFactoryConfiguration.EmbeddedJetty.class
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class
但是这三个类都有各自创建的条件比如tomcatConfiguration(proxyBeanMethods false)
// 这三个类在 类加载器里都存在
ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
//要是有用户自定义的 ServletWebServerFactory 类型的Bean就不创建
ConditionalOnMissingBean(value ServletWebServerFactory.class, search SearchStrategy.CURRENT)
static class EmbeddedTomcat {//这里的ObjectProvider 意思就是有了就设置进去没了设置一个内容为空的对象//给对Tomcat进行自定义设置的一个扩展再配置无法满足需求的时候BeanTomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProviderTomcatConnectorCustomizer connectorCustomizers,ObjectProviderTomcatContextCustomizer contextCustomizers,ObjectProviderTomcatProtocolHandlerCustomizer? protocolHandlerCustomizers) {TomcatServletWebServerFactory factory new TomcatServletWebServerFactory();factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));return factory;}
}注意 ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class }) 这个注解里依赖的 class即使不存在也没关系 因为编译和运行都不会报错 因为本来我们应用里依赖的就是 jar包 jar包就是编译好的class文件所以不会再重复编译了 运行的时候也不是直接反射而是利用ASM技术直接读的字节码获取引用类的全类名 然后调用类加载器加载加载不到就是没有
getWebServer():
Tomcat tomcat new Tomcat();
然后进行各种设置 下面三个日志就是这一步打印的
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
o.apache.catalina.core.StandardService : Starting service [Tomcat]
org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.71]总之就是创建了服务 但是没有真正的启动因为关系是这样的 上下文的refresh()方法中
// Initialize other special beans in specific context subclasses.
// 此时还在这里
onRefresh();// Check for listener beans and register them.
registerListeners();// Instantiate all remaining (non-lazy-init) singletons.
// 创建 非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.
// 最后一步 到这里 所有Bean都已经ok了 可以提供服务出来了
finishRefresh();执行WebServer#start
finishRefresh() 中
getLifecycleProcessor().onRefresh() 中的 onRefresh()
onRefresh() startBeans(true);startBeans(true)
获取beanFactory 中所有的 Lifecycle.class 类型的Bean 设置到 MapString, Lifecycle lifecycleBeansMapInteger, LifecycleGroup phases new TreeMap();
遍历 lifecycleBeans : (beanName, bean){if (bean instanceof SmartLifecycle bean.isAutoStartup())) {int phase getPhase(bean);//这个就是说如果map的value已存在 那么就add(beanName, bean)//不存在就创建phases.computeIfAbsent(phase,p - new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)).add(beanName, bean);if (!phases.isEmpty()) {//这里就执行了 bean.start();//也就是日志o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path phases.values().forEach(LifecycleGroup::start);}}
}自动配置
我们经常用的比如改端口
server.prot8080是怎么实现的呢
读取配置
//这个注释意思是如果这个类没有加载 那么ServerProperties这个类也不需要加载了
EnableConfigurationProperties(ServerProperties.class)
public class ServletWebServerFactoryAutoConfiguration {}ConfigurationProperties(prefix server, ignoreUnknownFields true)
public class ServerProperties {private Integer port;...
}这里就是读取配置 那再哪里修改的呢
修改配置
Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,...}
public class ServletWebServerFactoryAutoConfiguration {}BeanPostProcessorsRegistrar 在 registerBeanDefinitions 方法中注册了WebServerFactoryCustomizerBeanPostProcessor在 WebServerFactoryCustomizerBeanPostProcessor 的 postProcessBeforeInitialization 方法中遍历所有 WebServerFactoryCustomizer.class 类的Bean : customizer {customizer.customize(webServerFactory);
}哪里注册了 WebServerFactoryCustomizer
public class ServletWebServerFactoryAutoConfiguration {Beanpublic ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties){...}...
}在 org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer#customize 中Override
public void customize(ConfigurableServletWebServerFactory factory) {PropertyMapper map PropertyMapper.get().alwaysApplyingWhenNonNull();//存在配置 则调用setPortmap.from(this.serverProperties::getPort).to(factory::setPort);map.from(this.serverProperties::getAddress).to(factory::setAddress);...
}也就是调用了ConfigurableServletWebServerFactory 的setPort最终读取
在 org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer 中
Tomcat tomcat new Tomcat();
...
Connector connector new Connector(this.protocol);
...
customizeConnector(connector);其中customizeConnector(connector)
int port Math.max(getPort(), 0);
connector.setPort(port);其中getPort():
获取属性port 默认是 8080