SpringBoot嵌入式Servlet容器自动配置原理
2021-04-23 06:30
标签:removes spring rtb style dde var object and deploy 写点感悟,已经一年多没有写博客了,日常工作遇到问题也是记录在有道云里面。回想一下,毕业两年,刚毕业时很多人看好,到现在和去大厂的同学差距应该无法想象了。为什么?还是太安逸了,压力驱动型性格在这种环境下迷失了。每天都说学习,但是却一天拖一天,从心底说服自己玩远远比说服自己学习容易,两年。本可以成长很多,但是却在工作简单的业务中沉沦了。也很奇怪,当某一根筋被触动后,却又变化很多,还是有进步的心吧。定下长远规划,打好基础,不计较一时得失,拉下的慢慢追吧! Servlet容器的自动配置是通过ServletWebServerFactoryAutoConfiguration 自动配置类来实现的,先不看里面方法,从类注解看起。 首先略过BeanPostProcessorsRegistrar,来看EmbeddeTomcat.class 其实只干了一件事,就是将TomcatServletWebServerFactory 注册到容器当中,点开TomcatServletWebServerFactory 看一下。 里面关键是这个方法 其实用用java生成了一个tomcat,然后继续点击getTomcatWebServer,TomcatServletWebServerFactory 会新创建类一个TomcatWebServer 在不修改端口号的情况下TomcatServletWebServerFactory 默认配置端口为8080 同理EmbeddedJetty与EmbeddedUndertow也是如此。 那么我们如何自定义相关配置,又如何生效呢? 有两种方式: 1、通过application.yml里面配置。如何生效? 回到最上面,引入ServerProperties。打开看一下 配置内容与bean绑定以后如何生效的呢?下面就用到了自动配置类里面的代码 注册ServletWebServerFactoryCustomizer与TomcatServletWebServerFactoryCustomizer两个对象到Spring容器中时传入。 打开两个类可以看到在customize方法里面会被应用,去配置对应的容器工厂类。联系上面,工厂类是用来注册容器实例的,那么这个customize这个配置一定会在此之前被调用,什么时候呢?这时候来看开头忽略的Import 这一行是关键,打开 通过 我们在application里面配置的内容就应用到了其中。 另一种是就是自定义的WebServerFactory,可以 将我们自定义的ConfigurableServletWebServerFactory注入到了Spring容器中 这样自定义的Factory就不会生效了。 有一个疑问,我只找到了 并没有找到像 Jetty和Undertow的Customizer的注册Bean SpringBoot嵌入式Servlet容器自动配置原理 标签:removes spring rtb style dde var object and deploy 原文地址:https://www.cnblogs.com/wxw7blog/p/13270152.html@Configuration(
proxyBeanMethods = false
) //表示这个一个配置类
@AutoConfigureOrder(-2147483648)
@ConditionalOnClass({ServletRequest.class}) //只有包含ServletRequest这个类的时候此配置类才会生效
@ConditionalOnWebApplication(
type = Type.SERVLET
)//当前是web环境
@EnableConfigurationProperties({ServerProperties.class})//启动指定类的ConfigurationProperties功能;将配置文件中对应的值和ServerProperties绑定起来;并把ServerProperties加入到ioc容器中
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})//导入这四个Bean到容器中,下面详细讲解
public class ServletWebServerFactoryAutoConfiguration {
}
@ConditionalOnClass({Servlet.class, Tomcat.class, UpgradeProtocol.class})//只有包含Tomcat类时才会生效,不同的Servlet容器引入jar包不同,Jetty与UnderTow的配置也是通过这个区分
@ConditionalOnMissingBean(
value = {ServletWebServerFactory.class},
search = SearchStrategy.CURRENT
)//当系统中没有ServletWebServerFactory时,才会使用下面创建的、//ServletWebServerFactory,通过这其实可以看出,我们可以自定义ServletWebServerFactory来实现自己的配置
static class EmbeddedTomcat {
EmbeddedTomcat() {
}
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.getTomcatConnectorCustomizers().addAll((Collection)connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers().addAll((Collection)contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers().addAll((Collection)protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
this.customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
this.configureEngine(tomcat.getEngine());
Iterator var5 = this.additionalTomcatConnectors.iterator();
while(var5.hasNext()) {
Connector additionalConnector = (Connector)var5.next();
tomcat.getService().addConnector(additionalConnector);
}
this.prepareContext(tomcat.getHost(), initializers);
return this.getTomcatWebServer(tomcat);
}
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, this.getPort() >= 0, this.getShutdown());
}
public int getPort() {
return this.port;
}
private int port = 8080;
public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
this.monitor = new Object();
this.serviceConnectors = new HashMap();
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
this.gracefulShutdown = shutdown == Shutdown.GRACEFUL ? new GracefulShutdown(tomcat) : null;
this.initialize(); //执行初始化
}
private void initialize() throws WebServerException {
logger.info("Tomcat initialized with port(s): " + this.getPortsDescription(false));
synchronized(this.monitor) {
try {
this.addInstanceIdToEngineName();
Context context = this.findContext();
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && "start".equals(event.getType())) {
this.removeServiceConnectors();
}
});
this.tomcat.start();//tomcat被启动
this.rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), this.getClass().getClassLoader());
} catch (NamingException var5) {
}
this.startDaemonAwaitThread();
} catch (Exception var6) {
this.stopSilently();
this.destroySilently();
throw new WebServerException("Unable to start embedded Tomcat", var6);
}
}
}
@ConfigurationProperties(
prefix = "server",
ignoreUnknownFields = true
)//是与配置文件中的server下的内容绑定,我们能配置的内容也就是下面下面这些
public class ServerProperties {
private Integer port;
private InetAddress address;
@NestedConfigurationProperty
private final ErrorProperties error = new ErrorProperties();
private ServerProperties.ForwardHeadersStrategy forwardHeadersStrategy;
private String serverHeader;
private DataSize maxHttpHeaderSize = DataSize.ofKilobytes(8L);
private Shutdown shutdown;
@NestedConfigurationProperty
private Ssl ssl;
@NestedConfigurationProperty
private final Compression compression;
@NestedConfigurationProperty
private final Http2 http2;
private final ServerProperties.Servlet servlet;
private final ServerProperties.Tomcat tomcat;
private final ServerProperties.Jetty jetty;
private final ServerProperties.Netty netty;
private final ServerProperties.Undertow undertow;
}
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnClass(
name = {"org.apache.catalina.startup.Tomcat"}
)
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
public class ServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer
public class TomcatServletWebServerFactoryCustomizer implements WebServerFactoryCustomizer
BeanPostProcessorsRegistrar
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
public BeanPostProcessorsRegistrar() {
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this.beanFactory = (ConfigurableListableBeanFactory)beanFactory;
}
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (this.beanFactory != null) {
this.registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class);
this.registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor", ErrorPageRegistrarBeanPostProcessor.class);
}
}
private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
this.registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class);
public class WebServerFactoryCustomizerBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List
//对Spring容器中的WebServerFactory执行customize方法。
customizer.customize(webServerFactory);
});
}
private Collection customizer.customize(webServerFactory);
@Configuration
public class WebConfigurer {
@Bean
public ConfigurableServletWebServerFactory configurableServletWebServerFactory(){
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(8585);
return factory;
}
}
@ConditionalOnMissingBean(
value = {ServletWebServerFactory.class},
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnClass(
name = {"org.apache.catalina.startup.Tomcat"}
)
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
上一篇:python发送邮件
下一篇:CSS3
文章标题:SpringBoot嵌入式Servlet容器自动配置原理
文章链接:http://soscw.com/index.php/essay/78436.html