电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

SpringBoot如何實現Tomcat自動配置

瀏覽:84日期:2023-03-21 14:25:57

目錄

準備工作

我們知道SpringBoot的自動裝配的秘密在 org.springframework.boot.autoconfigure 包下的 spring.factories 文件中,而嵌入Tomcat的原理就在這個文件中加載的一個配置類: org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration

@Configuration@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@ConditionalOnClass(ServletRequest.class)@ConditionalOnWebApplication(type = Type.SERVLET)@EnableConfigurationProperties(ServerProperties.class)@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,ServletWebServerFactoryConfiguration.EmbeddedJetty.class,ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })public class ServletWebServerFactoryAutoConfiguration {@Beanpublic 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);}/** * Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via * {@link ImportBeanDefinitionRegistrar} for early registration. */public static class BeanPostProcessorsRegistrarimplements ImportBeanDefinitionRegistrar, BeanFactoryAware {private ConfigurableListableBeanFactory beanFactory;@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {if (beanFactory instanceof ConfigurableListableBeanFactory) {this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;}}@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {if (this.beanFactory == null) {return;}registerSyntheticBeanIfMissing(registry,'webServerFactoryCustomizerBeanPostProcessor',WebServerFactoryCustomizerBeanPostProcessor.class);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);}}}}

首先看一下上方的幾個注解

@AutoConfigureOrder 這個注解是決定配置類的加載順序的,當注解里的值越小越先加載,而 Ordered.HIGHEST_PRECEDENCE 的值是 Integer.MIN_VALUE 也就是說這個類肯定是最先加載的那一批 @ConditionalOnXXX 在之前的文章中已經無數次提到了,就不再闡述了 @EnableConfigurationProperties 開啟 ServerProperties 類的屬性值配置。而這個類里面包含的就是Web服務的配置

@ConfigurationProperties(prefix = 'server', ignoreUnknownFields = true)public class ServerProperties {private Integer port;private InetAddress address;@NestedConfigurationPropertyprivate final ErrorProperties error = new ErrorProperties();private Boolean useForwardHeaders;private String serverHeader;private int maxHttpHeaderSize = 0; // bytesprivate Duration connectionTimeout;@NestedConfigurationPropertyprivate Ssl ssl;@NestedConfigurationPropertyprivate final Compression compression = new Compression();@NestedConfigurationPropertyprivate final Http2 http2 = new Http2();private final Servlet servlet = new Servlet();private final Tomcat tomcat = new Tomcat();private final Jetty jetty = new Jetty();private final Undertow undertow = new Undertow();}

這個類的代碼太多了,這里就不一一貼出來了,我們平常在 application.properties 中配置的server.xxx就是這個類中屬性

@ImportBeanPostProcessorsRegistrarpublic static class BeanPostProcessorsRegistrarimplements ImportBeanDefinitionRegistrar, BeanFactoryAware {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {if (this.beanFactory == null) {return;}registerSyntheticBeanIfMissing(registry,'webServerFactoryCustomizerBeanPostProcessor',WebServerFactoryCustomizerBeanPostProcessor.class);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);}}}

這個類注冊了兩個bean: WebServerFactoryCustomizerBeanPostProcessor 和 ErrorPageRegistrarBeanPostProcessor 關于這兩個bean的作用稍后再詳細介紹

EmbeddedTomcat

@Configuration@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)public static class EmbeddedTomcat { @Bean public TomcatServletWebServerFactory tomcatServletWebServerFactory() { return new TomcatServletWebServerFactory(); }}

這個類會在存在Tomcat相關jar包時添加一個 TomcatServletWebServerFactory bean

其他兩個相信大家都知道怎么回事了

除了這些這個類還注入了兩個類 ServletWebServerFactoryCustomizer 和 TomcatServletWebServerFactoryCustomizer現在前期準備工作已經做好了,看一下這個Tomcat是如何啟動的吧

啟動

啟動入口在 ServletWebServerApplicationContext 中的 onRefresh 方法

protected void onRefresh() {super.onRefresh(); try { createWebServer(); }catch (Throwable ex) {throw new ApplicationContextException('Unable to start web server', ex);}}

Tomcat的啟動就在 createWebServer 方法里面了

private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = getServletContext(); //第一次訪問的時候兩個對象都為空 if (webServer == null && servletContext == null) { ServletWebServerFactory factory = getWebServerFactory(); this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException('Cannot initialize servlet context', ex); } } initPropertySources();}

首先看一下 getWebServerFactory

protected ServletWebServerFactory getWebServerFactory() { // 這里獲取的beanname就是上方注冊的tomcatServletWebServerFactory了 String[] beanNames = getBeanFactory() .getBeanNamesForType(ServletWebServerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException( 'Unable to start ServletWebServerApplicationContext due to missing ' + 'ServletWebServerFactory bean.'); } if (beanNames.length > 1) { throw new ApplicationContextException( 'Unable to start ServletWebServerApplicationContext due to multiple ' + 'ServletWebServerFactory beans : ' + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);}

準備環境里注冊的bean現在出來一個了。注意,上方還注冊了一個后置處理器 EmbeddedServletContainerCustomizerBeanPostProcessor ,獲取bean tomcatServletWebServerFactory 的時候就會執行后置處理器的 postProcessBeforeInitialization 方法

public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {if (bean instanceof WebServerFactory) {postProcessBeforeInitialization((WebServerFactory) bean);}return bean;}private void postProcessBeforeInitialization(WebServerFactory webServerFactory) { LambdaSafe .callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory) .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class) .invoke((customizer) -> customizer.customize(webServerFactory));}private Collection<WebServerFactoryCustomizer<?>> getCustomizers() { if (this.customizers == null) { // Look up does not include the parent context this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans()); this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE); this.customizers = Collections.unmodifiableList(this.customizers); } return this.customizers;}@SuppressWarnings({ 'unchecked', 'rawtypes' })private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() { return (Collection) this.beanFactory .getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();}

這個處理器的作用是獲得所有定制器,然后執行定制器的方法

接著往下看

這個時候就可以啟動Tomcat了

public WebServer getWebServer(ServletContextInitializer... initializers) { Tomcat tomcat = new 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); return getTomcatWebServer(tomcat);}protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) { return new TomcatWebServer(tomcat, getPort() >= 0);}public TomcatWebServer(Tomcat tomcat, boolean autoStart) { Assert.notNull(tomcat, 'Tomcat Server must not be null'); this.tomcat = tomcat; this.autoStart = autoStart; initialize();}private void initialize() throws WebServerException { TomcatWebServer.logger.info('Tomcat initialized with port(s): ' + getPortsDescription(false)); synchronized (this.monitor) { try { addInstanceIdToEngineName(); Context context = findContext(); context.addLifecycleListener((event) -> { if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) { // Remove service connectors so that protocol binding doesn’t // happen when the service is started. removeServiceConnectors(); } }); // Start the server to trigger initialization listeners this.tomcat.start(); // We can re-throw failure exception directly in the main thread rethrowDeferredStartupExceptions(); try { ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader()); } catch (NamingException ex) { // Naming is not enabled. Continue } // Unlike Jetty, all Tomcat threads are daemon threads. We create a // blocking non-daemon to stop immediate shutdown startDaemonAwaitThread(); } catch (Exception ex) { throw new WebServerException('Unable to start embedded Tomcat', ex); } }}

以上就是SpringBoot如何實現Tomcat自動配置的詳細內容,更多關于SpringBoot實現Tomcat自動配置的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
主站蜘蛛池模板: 学校用栓剂模,玻璃瓶轧盖钳,小型安瓿熔封机,实验室安瓿熔封机-长沙中亚制药设备有限公司 | 长沙广告公司|长沙广告制作设计|长沙led灯箱招牌制作找望城湖南锦蓝广告装饰工程有限公司 | 吉林污水处理公司,长春工业污水处理设备,净水设备-长春易洁环保科技有限公司 | 盘式曝气器-微孔曝气器-管式曝气器-曝气盘-斜管填料 | 郑州市前程水处理有限公司 | 振动筛,震动筛,圆形振动筛,振动筛价格,振动筛厂家-新乡巨宝机电 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 两头忙,井下装载机,伸缩臂装载机,30装载机/铲车,50装载机/铲车厂家_价格-莱州巨浪机械有限公司 | 托利多电子平台秤-高精度接线盒-托利多高精度电子秤|百科 | 120kv/2mA直流高压发生器-60kv/2mA-30kva/50kv工频耐压试验装置-旭明电工 | 电镀电源整流器_高频电解电源_单脉双脉冲电源 - 东阳市旭东电子科技 | 精雕机-火花机-精雕机 cnc-高速精雕机-电火花机-广东鼎拓机械科技有限公司 | 激光内雕_led玻璃_发光玻璃_内雕玻璃_导光玻璃-石家庄明晨三维科技有限公司 激光内雕-内雕玻璃-发光玻璃 | 小程序开发公司_APP开发多少钱_软件开发定制_微信小程序制作_客户销售管理软件-济南小溪畅流网络科技有限公司 | 北京浩云律师事务所-企业法律顾问_破产清算等公司法律服务 | 丹尼克尔拧紧枪_自动送钉机_智能电批_柔性振动盘_螺丝供料器品牌 | 在线钠离子分析仪-硅酸根离子浓度测定仪-油液水分测定仪价格-北京时代新维测控设备有限公司 | 自动钻孔机-全自动数控钻孔机生产厂家-多米(广东)智能装备有限公司 | 磁力加热搅拌器-多工位|大功率|数显恒温磁力搅拌器-司乐仪器官网 | 定制液氮罐_小型气相液氮罐_自增压液氮罐_班德液氮罐厂家 | ph计,实验室ph计,台式ph计,实验室酸度计,台式酸度计 | 【化妆品备案】进口化妆品备案流程-深圳美尚美化妆品有限公司 | 动库网动库商城-体育用品专卖店:羽毛球,乒乓球拍,网球,户外装备,运动鞋,运动包,运动服饰专卖店-正品运动品网上商城动库商城网 - 动库商城 | 中高频感应加热设备|高频淬火设备|超音频感应加热电源|不锈钢管光亮退火机|真空管烤消设备 - 郑州蓝硕工业炉设备有限公司 | 共享雨伞_共享童车_共享轮椅_共享陪护床-共享产品的领先者_有伞科技 | 起好名字_取个好名字_好名网免费取好名在线打分 | 电伴热系统施工_仪表电伴热保温箱厂家_沃安电伴热管缆工业技术(济南)有限公司 | 高铝矾土熟料_细粉_骨料_消失模_铸造用铝矾土_铝酸钙粉—嵩峰厂家 | 车牌识别道闸_停车场收费系统_人脸识别考勤机_速通门闸机_充电桩厂家_中全清茂官网 | 重庆监控_电子围栏设备安装公司_门禁停车场管理系统-劲浪科技公司 | 杭州代理记账费用-公司注销需要多久-公司变更监事_杭州福道财务管理咨询有限公司 | 薄壁轴承-等截面薄壁轴承生产厂家-洛阳薄壁精密轴承有限公司 | 石英砂矿石色选机_履带辣椒色选机_X光异物检测机-合肥幼狮光电科技 | 深圳彩钢板_彩钢瓦_岩棉板_夹芯板_防火复合彩钢板_长鑫 | 塑钢课桌椅、学生课桌椅、课桌椅厂家-学仕教育设备首页 | 铁盒_铁罐_马口铁盒_马口铁罐_铁盒生产厂家-广州博新制罐 | 滤芯,过滤器,滤油机,贺德克滤芯,精密滤芯_新乡市宇清流体净化技术有限公司 | 西安展台设计搭建_西安活动策划公司_西安会议会场布置_西安展厅设计西安旭阳展览展示 | 砂石生产线_石料生产线设备_制砂生产线设备价格_生产厂家-河南中誉鼎力智能装备有限公司 | POS机办理_个人POS机免费领取 - 银联POS机申请首页 | 超声波清洗机_超声波清洗机设备_超声波清洗机厂家_鼎泰恒胜 | 氧氮氢联合测定仪-联测仪-氧氮氢元素分析仪-江苏品彦光电 | 郑州宣传片拍摄-TVC广告片拍摄-微电影短视频制作-河南优柿文化传媒有限公司 |