二、何为Spring Boot整合Spring Cloud?
题语:学习方法之多思考:正向、逆向、跳跃
作者:A哥(YourBatman)
wx号:fsx641385712(备注“Java群”字样)
公众号:BAT的乌托邦(ID:BAT-utopia)
代码下载地址:https://github.com/f641385712/netflix-learning
目录
- 前言
- 正文
- Spring Boot整合Spring Cloud
- 概念辨析
- 应用 vs 上下文 vs 容器
- 应用Application
- 上下文Context
- 容器
- 父容器 vs 子容器
- Environment环境
- 属性源
- 我该如何记忆Spring Boot属性优先级?
- 附:Spring Boot所有版本外部化配置一览
- 2020-11-22新增
- application.yaml vs bootstrap.yaml
- 总结
- 关注A哥
前言
各位小伙伴大家好,我是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的子类:AnnotationConfigServletWebServerApplicationContext
和AnnotationConfigApplicationContext
(前者由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容器/上下文的组织中,如HierarchicalBeanFactory
。ApplicationContext#getParent()
能证明Spring的上下文也是具有层级结构的。
同义词:父上下文、子上下文。但是切记不可说成父应用和子应用,因为一个Spring Boot工程只会有一个应用,而一个应用内可以有N多个上下文,它们之间可以有关,亦可无关,这是合理的。
Environment环境
一般我喜欢叫它Spring的环境抽象,该“实例”代表着上下文的运行环境,主要包含如下三部分内容:
PropertySource
:属性源。key-value属性对抽象。环境内会有多个属性源,使用MutablePropertySources
来组织PropertyResolver
:属性解析器。用于解析相应key的value,比如你熟悉的PropertySourcesPropertyResolver
就是实现Profile
:配置(资料里翻译为剖面、侧面,也是阔仪的)。只有激活的配置profile的组件/配置才会注册到Spring容器,类似于maven中profile
Environment
抽象Spring一共提供了三个实现类:
- 用于非web环境的:
StandardEnvironment
- 用于web环境的:
StandardServletEnvironment
和StandardReactiveWebEnvironment
,他俩均为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已经发布,它带来了全新的配置文件加载机制,不具备向下兼容性,因此本处特别的过来加上。
它官网对配置文件顺序描述也发生了变化,如下图:
阅读此部分配置项需要注意:
- 文档中排列顺序不同于以往,这里是倒序(既最后面的是优先级越高的),请查看时注意哦
- Config data(序号是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,特此提醒各位不要“学我”哦
关注A哥
Author | A哥(YourBatman) |
---|---|
个人站点 | www.yourbatman.cn |
yourbatman@qq.com | |
微 信 | fsx641385712 |
活跃平台
|
|
公众号 | BAT的乌托邦(ID:BAT-utopia) |
知识星球 | BAT的乌托邦 |
每日文章推荐 | 每日文章推荐 |
- Netflix OSS套件一站式学习驿站
- Netflix OSS套件一站式学习驿站
- 一、为何我决定写Spring Cloud专栏
二、何为Spring Boot整合Spring Cloud?相关推荐
- 认证与授权流程与spring boot整合 spring security(1)
一 spring security 1.1 spring security的作用 Spring Security所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截 ...
- spring boot整合spring security笔记
最近自己做了一个小项目,正在进行springboot和spring Security的整合,有一丢丢的感悟,在这里分享一下: 首先,spring boot整合spring security最好是使用T ...
- springboot整合hibernate_峰哥说技术系列-17 .Spring Boot 整合 Spring Data JPA
今日份主题 Spring Boot 整合 Spring Data JPA JPA(Java Persistence API)是用于对象持久化的 API,是Java EE 5.0 平台标准的 ORM 规 ...
- Spring boot 整合Spring Security Jwt
记录学习Spring boot 整合Spring Security Jwt 学习参考 – 慢慢的干货 https://shimo.im/docs/OnZDwoxFFL8bnP1c/read 首先创建S ...
- Spring Boot 整合——Spring batch重试和回滚
关于版本 依赖 版本 springboot 2.4.0 spring batch 2.4.0 代码地址 因为每个例子涉及代码较多,且包含测试用例,如果都贴到文章中内容过多,所以只贴出了部分代码.全部的 ...
- spring boot 整合 spring cache 简单使用
spring boot 整合 spring cache 简单使用 spring cache简介 使用spring cache spring cache简介 Spring 3.1起,提供了基于注解的对C ...
- Spring Boot 整合——Spring Boot整合kafka整合
Spring Boot 整合之前的内容 项目名称 描述 地址 base-data-mybatis 整合mybatis-plus(实际上官方教程已经很多,只做了自定义插件) 未完成 base-jpa J ...
- Spring Boot整合Spring Data JPA操作数据
一. Sping Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 J ...
- Spring Boot 整合 Spring Security 示例
点击关注公众号,Java干货及时送达 一.说明 SpringSecurity是一个用于Java 企业级应用程序的安全框架,主要包含用户认证和用户授权两个方面.相比较Shiro而言,Security功能 ...
最新文章
- 终端多窗口管理旗舰------screen
- Jquery中怎样判断是否有网络
- 转载:Linux命令之查看文件占用空间大小-du,df
- 【故障诊断分析】基于matlab FFT轴承故障诊断【含Matlab源码 1397期】
- php7 switch,Switch autocommit on or off - PHP 7 中文文档
- Android 四大组件
- html 内容写入数据库中,FoxPro数据库写入html文件中
- PFC离散元仿真核心技术与应用
- CodeForces - 1299B. Aerodynamic
- 《RISC-V架构与嵌入式开发快速入门_胡振波著》学习笔记
- 久邦GOMO总裁朱志在2018校招生交流会分享
- SpringBoot实现QQ邮箱注册和登录
- Linux命令学习总结
- 数据标注是做什么的?
- TVB经典电视剧--《创世纪》回忆
- Visual Studio 2019解决右侧工具栏消失
- 详解软件无线电(SDR)架构
- ModStartBlog 现代化个人博客系统 v5.2.0 源码下载
- 《计算机图形学编程(使用OpenGL和C++)》
- SpringBoot中使用AMQ的两种方式二(Java配置、注解方式)