前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >二、何为Spring Boot整合Spring Cloud?

二、何为Spring Boot整合Spring Cloud?

作者头像
YourBatman
发布2020-11-24 11:33:13
7260
发布2020-11-24 11:33:13
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦

代码下载地址:https://github.com/f641385712/netflix-learning

目录

前言

各位小伙伴大家好,我是A哥。通过上文 为何我决定写Spring Cloud专栏 一方面了解了A哥的“创作背景”;另一方面,当然也是最主要的便是我们已经初步了解了Spring Cloud Context工程,并且对它的spring.factories文件做了介绍,从中是能窥探出SC的核心组成“元素”的。

天若有情天亦老,人间正道是沧桑。接下来会进入到“枯燥乏味”的修行当中,坚持下来的都是英雄。准备深入去了解Spring Cloud,BootstrapApplicationListener无疑是它的第一入口,然而在这之前,我们依旧需要扫除一些“障碍”。


正文

关于Spring Boot整合,请看我在度娘上的搜索推荐结果:


Spring Boot整合Spring Cloud

众所周知,Spring Cloud是构建在一个Spring Boot应用的基础之上的,广义上说可以认为是SB应用把Spring Cloud整合进来了。谈到技术整合相信各位小伙伴轻车熟路:Redis整合、ElasticSearch整合、MyBatis整合…Spring Cloud的整合方式有点不太一样。SC它并非作为一个组件那么直接的加入到Spring Boot的ApplicationContext上下文/容器里即可,而是拥有自己一套独立的ApplicationContext上下文,然后通过上下文之间的关系(父子关系)完成和Spring Boot的“整合”。

如果说Mybatis、Redis这种整合方式是单个、直接方式;那么Spirng Cloud这种便是批量的、间接的方式,而正因为Spring Cloud有自己的Context上下文,所以它自己也就拥有整合其它组件的能力,这是非常重要的。

其实把Eureka、Hystrix、Ribbon等和Spring Boot直接整合也是可行的,但是这并不符合SB单应用的定位,并且Spring Framework和Spring Boot团队并不擅长解决和网络、云计算相关的技术,因此专门开设Spring Cloud子项目负责“接管”,保证了Spring Boot的纯粹性


概念辨析

在正式开始Spring Cloud内容学习之前,我觉得有几个概念性的知识点需要先辨析一下,这个工作很有必要。


应用 vs 上下文 vs 容器

作为一个Java coder,这三个概念应该是常绕耳边的。不可否认,这三个概念非常重要,它亦会在本系列文章中贯穿始终,因为它就是用来沟通的“语言”嘛。但是,常常听见并不代表真的理解,特别这种“近义词”,本处就对这几个概念作出辨析。

以个人理解作出的小总结,若有误请留言指正,A哥一直都是个虚心向任何人学习的好孩纸


应用Application

应用是个比较大概念,比如一个QQ、微信我们均可称为是一个应用,而此处我们一般指的是Spring应用。比如我们一个Spring Boot工程就是一个SpringApplication实例,也就是一个Spring应用,另外它也称为主应用,一个工程主应用只会有一个

通常来讲,一个应用只有一个上下文,所以应用和上下文这两个概念常常被误以为是对等的,其实非也,他俩并非同一层面的东东。举个例子:以Spring Boot为例,有些监听器注册在SpringApplication应用上作用于监听应用的变化(如生命周期监听器、初始化器等),它们并没有放进Spring容器内所以对上下文无感;而有些监听器是被放进容器里的,它的作用区域便就是和容器、Bean相关喽

另外,需要知道的是SB和SC的context上下文均是通过SpringApplication来构建的,但该SpringApplication实例在构建出Context后一般随即就“消失了”,这也是很多小伙伴误认为应用 == 上下文的原因之一吧;另外,父子容器概念属于context上下文级别非应用级别


上下文Context

同理,我们一般指的是Spring上下文,也就是ApplicationContext。在SB/SC里,实际使用的是ConfigurableApplicationContext的子类:AnnotationConfigServletWebServerApplicationContextAnnotationConfigApplicationContext(前者由Spring Boot提供,后者由Spring Framework提供)。ApplicationContext是具有层级关系(父子关系)的,ApplicationContext#getParent()证明了这一点。

ApplicationContext上下文里的内容非常“丰富”,如Environment环境、BeanFactory工厂、协议解析器等等它都有,毕竟具备这些能力才算一个“合格的”上下文嘛。另外针对于在SC环境下的上下文情况需要有如下共识:

  • SB和SC各自拥有一个独立的上下文,它们之前互相隔离却又有联系:SC上下文是SB的父上下文

容器

容器这个概念就更抽象了,在Java界也有不少如web容器、servlet容器等等,但是大多数情况下(包括本系列文章)我们一般指的是IoC容器,也就是Spring容器。

说明:IoC容器的实现其实不仅仅只有Spring,还有也比较流行的Google的开源库Guice,也是个非常好用轻量级DI管理库,有一些第三方开源组件如Eureka、Ribbon、Druid等都是基于它构建的,有兴趣可自己玩玩,也可参考我文章有写到~

对于Spring容器,我们有时候也叫它Bean工厂,也即是BeanFactory嘛。实际上ApplicationContext继承了BeanFactory接口,所以也是个容器(高级别容器),因此在概念上:上下文和容器这两个概念一般是可以对等的

  • 槽点:Spring的Bean容器为毛命名为BeanFactory而不是BeanContainer呢?

对于一个应用(如SB应用),ApplicationContext上下文/容器是可以有多个的。上下文之间的“隔离性”是很好的,后面会看到Ribbon、Feign等它们均会有自己的上下文,也就是学SC一样,通过上下文级别间接的完成和Spring Boot应用的整合。

那么问题来了:何时直接整合?何时需要自己创建一个上下文来管理呢?该问题就作为课后作业,留给读者你自行思考哈~


父容器 vs 子容器

父子关系是一种分层思想,被广泛应用于Spring容器/上下文的组织中,如HierarchicalBeanFactoryApplicationContext#getParent()能证明Spring的上下文也是具有层级结构的。

同义词:父上下文、子上下文。但是切记不可说成父应用和子应用,因为一个Spring Boot工程只会有一个应用,而一个应用内可以有N多个上下文,它们之间可以有关,亦可无关,这是合理的。


Environment环境

一般我喜欢叫它Spring的环境抽象,该“实例”代表着上下文的运行环境,主要包含如下三部分内容:

  1. PropertySource:属性源。key-value属性对抽象。环境内会有多个属性源,使用MutablePropertySources来组织
  2. PropertyResolver:属性解析器。用于解析相应key的value,比如你熟悉的PropertySourcesPropertyResolver就是实现
  3. Profile:配置(资料里翻译为剖面、侧面,也是阔仪的)。只有激活的配置profile的组件/配置才会注册到Spring容器,类似于maven中profile

Environment抽象Spring一共提供了三个实现类:

  • 用于非web环境的:StandardEnvironment
  • 用于web环境的:StandardServletEnvironmentStandardReactiveWebEnvironment,他俩均为StandardEnvironment的子类。
    • 需要注意的是:后者StandardReactiveWebEnvironment由Spring Boot提供,而非Spring Framework源生

这里小带一句:很多同学把属性和配置傻傻分不清楚,其实他俩就是Properties(k-v)和Profile概念上的差异,但口头上经常混用,一般可认为讲的是同一回事,但是你心里必须清楚哈。毕竟和专业人士聊起来的时候,还是需要这些细节掌握的

尴尬爆料:今天猛然发现,之前好多文章里我把Environment单词写错了,写为了Enviroment,特此提醒各位不要“学我”哦


属性源

Spring通过Environment建模Spring应用运行的环境,这其中最为重要的非属性源莫属。一个属性源就是一个PropertySource,它可以来自任意地方,如常用的有:

  • systemProperties -> 来自 system.getProperties()
  • systemEnvironment -> system.getenv()
  • random -> 来自一个Random对象,可用于生成随机数(SB提供)
  • applicationConfig: [classpath:/application.yaml] -> SB主配置,这个太常见了吧

属性源的优先级决定了配置的优先级。Spring Boot对其外部化配置优先级有文档说明:Spring Boot外部化配置


我该如何记忆Spring Boot属性优先级?

答案:不要记。精确答案:不要强记,因为“记不住”的。我见过不少(非常多)小伙伴一遇到需要考虑Spring Boot属性优先级问题时,整头就大了,立马拿出自己的小本本,又或者去度娘里查,或许那会还在内心里骂自己:怎么老是记不住呢?甚至质疑自己:是不是真的老了?

我说的此现象,你是否躺枪?授之以鱼不如授之以渔,对于这种“高难度、易出错”的知识点,浮于表面总觉浅,掌握其本质才是永恒。当然我这里不会去详讲Spring Boot这块的知识点,但我还是呕心沥血的整理出一堆截图,告诉你为何你强行记忆是记不住的(如果你是“天才”你就可以跳过本文了):


附:Spring Boot所有版本外部化配置一览

Spring Boot从它的1.0.x版本到现在的2.2.x版本,对于外部化配置的支持几乎是一直在变化/增加的,这种不确定性也无疑在一定程度上增加了我们记忆的难度。下面我从其官方文档截图出了它所有版本(请忽略小版本号)对应的支持的外部化配置情况:

说明:以下所有截图都来自Spring Boot官方文档的外部化配置Externalized Configuration部分,优先级从高到低

1.0.0.RELEASE(7个):

1.1.0.RELEASE(9个):@PropertySource优先级有调整,增加了JNDI和random属性源支持

1.2.0.RELEASE(9个):

1.3.0.RELEASE(12个):增加了JSON格式配置、支持-{profile}.xxx格式的配置

1.4.0.RELEASE(15个):增加了@TestPropertySource支持、ServletConfig和ServletContext属性源的支持

1.5.0.RELEASE(17个):增加了对调试工具@Devtools配置的支持、@SpringBootTest#properties的支持

2.0.0.RELEASE(17个):

2.1.0.RELEASE(17个):

2.2.0.RELEASE(17个):从2.2.0版本后,官方文档采用H5来重写了,所以页面风格整体上有所改变(更高级些了有木有)

此处对@PropertySource属性源增加了文字解释:它在refresh()容器之前,该属性源是不会放进Environment里面的,也就是说在容器启动之前请不要使用它里面的k-v,这在日常使用请你务必注意~

从这能看出Spring Boot对外部化配置发展的脉络。即使从1.5.0版本后,外部化配置趋于稳定,但谁知道以后呢?对吧~况且,17个耶,你真记得住?最为致命的是:如果你的工程接入配置中心来获取配置,又或者你二次开发自定位你配置的位置,它们都还不在这17个行列里,那肿么办?怎么判断属性优先级呢?所以嘛,像这种case,不要强记,不要强记,不要强记。

2020-11-22新增

截至此时,Spirng Boot 2.4.0已经发布,它带来了全新的配置文件加载机制,不具备向下兼容性,因此本处特别的过来加上。

它官网对配置文件顺序描述也发生了变化,如下图:

阅读此部分配置项需要注意:

  1. 文档中排列顺序不同于以往,这里是倒序(既最后面的是优先级越高的),请查看时注意哦
  2. Config data(序号是3)被当作一个整体参与排序,它内部维持着自己的顺序,这样更方便理解了嘛
  3. 总的算下来还是17种方式(14 - 1(序号3) + 4(序号3的详细) = 17)

Spring Boot自2.4.0版本后对配置文件的加载方式完全不同于以往,具体原理分析、使用注意事项、迁移指导等,请参见此系列文章的详解:Spring Boot 2.4.0正式发布,全新的配置文件加载机制(不向下兼容)


application.yaml vs bootstrap.yaml

对于它俩的比较理应放在最后,但这里先睹为快。

  • application.yaml/properties被Spring Boot容器读取,也常常被我们称为主配置
  • bootstrap.yaml/properties被Spring Cloud容器读取,也常常被我们称为引导配置

bootstrap.yaml优先于application.yaml被加载。虽然前者是给Spring Cloud专用的,但是这个属性源最终也会“合并”到Spring Boot的属性源里面去,并且优先级高于**application.yaml**,所以Spring Boot里也可以使用。

说明:application.yaml里的属性,SC可是完全触碰不到的~


总结

本文有种复习Spring Framework的赶脚,因为大部分概念都是“老的”,但也是最为核心的。以上概念多多少少都会和整合扯上点关系,后面会有所体现。

为何我觉得概念理解如此重要?我觉得概念就像是用于沟通的语言,只有做到感念一致性沟通起来才能顺畅,因此我才觉得在系列开头穿插着书写本文是很有必要的,磨刀不误砍柴工嘛。

尴尬爆料:今天猛然发现,之前好多文章里我把Environment单词写错了,写为了Enviroment,特此提醒各位不要“学我”哦


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-04-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 前言
  • 正文
    • Spring Boot整合Spring Cloud
      • 概念辨析
      • 总结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档