Spring 核心技术与产品理念剖析【下】
- 3. Spring Cloud 蝶变重生
Spring 框架的升级演进都是围绕分层架构进行的,从简单到复杂,再回到简单的过程。如果我们没有经历过 Spring 最开始繁琐的配置,然后一步步精简,就根本体会不到为什么会有 Spring Boot。俗话说,乱世造英雄。在新旧时代交替阶段,原来统治世界的旧秩序正在慢慢失效,而新秩序尚未成型,那些建立或者依赖旧秩序的巨头会被惯性推着往前走,他们习惯性地用旧思维或眼光看待世界,所以他们无法正确地理解新时代,这也就是诞生新巨头的机会。随着手机等各种智能终端的普及,原本最大的开发领域从企业应用变成了互联网应用,而这也引发了计算、存储等需求的暴涨,云计算随即呼之而出。基础架构从传统演进到了云计算,与传统基础架构匹配的应用架构是单体式分层架构,而与云计算匹配的应用架构是什么样的呢?大时代需要远见,否则容易懵圈。

记得2013~2016这几年时间里,应用开发技术栈出现过一阵混乱,老兵哥所在公司原本有套统一的内部开发框架,就是对 Spring 进行封装、定制和扩展,适配公司内部的基础平台和通用组件,满足内部各种企业应用的开发需求。企业应用都是服务于内部办公无纸化、自动化的,用户规模和并发访问量都是可以预估的,单体式分层架构就足够了。但随着互联网的发展,越来越多的业务开始上线,包括营销、客服等,互联网用户量不断增长,并发访问量波峰波谷的差值也越来越大,单体式分层架构显然无法满足业务发展要求了。
当时在互联网领域走得比较靠前的企业,开始在业务驱动下摸着石头过河了,那时候就出现了面向服务架构 SOA 和Web Service,Spring 最最擅长的领域就是企业应用开发,但对如何满足互联网应用的需求也有些摸不准方向,业界也开始出现许多新物种,其中最火爆的就是阿里的 Dubbo,曾经有种说法是 Dubbo 要代替 Spring。Web Service 就像当年的 EJB,过于复杂臃肿,但在没有更好选择的情况下,许多企业都采用了 Web Service。直到 RESTful 等新架构技术出现,以及 Netflix 探索出了微服务架构,业界才找到了应对互联网化的法宝。
Pivotal,Spring 的东家,在 Netflix 探索微服务架构时期,它正好在为 Netflix 提供咨询服务。当微服务架构被验证可行之后,Spring 就顺势将 Netflix 微服务全家桶 Netflix OSS 纳入到 Spring Cloud 当中,组件包括:Eureka、Zuul、Ribbon、Hystrix、Archaius 等。凭借这套解决方案在技术上的先进性和成熟度,以及原先遍布全球的无数粉丝用户,Spring 在云计算时代重新回到了 Java 应用开发框架的头把交椅上。Spring Boot 降低了单个应用的开发难度,Spring Cloud 降低了分布式系统的开发难度,强强联合,所向披靡。
随着 Spring Cloud 的地位越来越稳固,它的生态也开始发生了些变化,首先 Netflix 宣布 Eureka 闭源,后来 Netflix 宣布 Hystrix 停止新功能开发。同时,Spring Cloud 也从依赖生态伙伴提供关键组件,演变到自研适配关键组件,例如:Spring Cloud Gateway、Spring Cloud Config、Spring Cloud LoadBalance 等。
J2EE 在应用开发当中所扮演的角色也在不断演进,最初 J2EE、Spring 相关的应用会被部署至应用服务器,而现如今在 Spring Boot 的支持下,应用程序可以采用 DevOps、云原生的开发模式,Servlet 容器被内嵌在发布物当中。在 Spring 5.x 之后,采用 WebFlux 的应用可以不依赖任何 Servlet API,也可以部署在非 Servlet 容器的服务器当中,例如:Netty 等。Spring 还在不断创新和演进,除了 Spring Framework 之外,它还包含许多子工程:Spring Boot、Spring Security、Spring Data、Spring Cloud、Spring Batch 等。至此,Spring Cloud 成功蝶变了。
- 4. Spring 的产品设计理念
Spring 的发展状态不是一蹴而就的,先从点到线,再从线到面。最初仅实现了 IoC、AOP 等核心特性,支持单体式分层架构,再到 Spring Cloud 标准化不同系统之间的交互方式,同时不断构筑起丰富强大的生态圈。Spring 的成功不光是技术层面的,更主要是产品设计理念层面的,技术上的领先很容易被模仿抄袭,而理念差距却很难跨越。
乐高(LEGO),来自童话王国丹麦的玩具品牌,历经80多年的发展成为世界玩具市场的领导品牌,并以强大的实力跻身世界500强(第96位)。它旗下的产品以其独特的组合结构而风靡全球,得到了不计其数的孩子们甚至成年人的热爱与收藏。这家公司现在的产品是几种基本形状的塑料颗粒,最初它从制造木质玩具开始的,后来转而生产塑料玩具,但玩具市场跟服装市场类似,每年都有不同的流行款式,乐高也做不到每年都准确预测玩具流行趋势,生意不愠不火。
后来企业传到了创始人的儿子手上,一个偶然的机会有个玩具经销商建议他生产可拼装玩具,这样玩家就可以拼装各式各样的玩具,乐高也就永远不会过时了,大部分颗粒的模具都可以重复使用。从此,乐高开始一发不可收拾,产品热销全球,而且玩家自发地组成各种社区交流经验,为乐高的发展贡献了无数智慧。但随着电子玩具和游戏的兴起,乐高这种搭建体验式的玩具受到了冲击,直到有玩家利用单片机、电动马达、传感器和积木搭建出了可编程、可运动和可遥控的机器人等作品,乐高又重新回到市场领导者地位。
之所以讲述乐高的发展史,是因为它跟 Spring 的成功有着类似的原因,首先提供简单、轻量和易用的基础组件,再提供可编程的装配能力,对乐高来说就是用于衔接积木的标准凹凸卡扣,以及可编程的单片机,对于 Spring 来说就是通过 XML、Annotation 或 Java 类等配置控制装配过程的 IOC,以及标准化装配辅助功能 AOP。等有了丰富的基础组件和可编程的装配能力之后,玩家或用户就拥有了灵活性,可以天马行空发挥聪明才智创造出各类作品了。
相对于全球玩家或用户的群体智慧来说,单个公司所能雇佣的人才就非常有限了,Spring 的产品设计理念是面向群体智慧开放的,它的灵活性激发了用户的创造力,同时它通过开源汇聚了全球群体智慧,构建起强大的生态圈,这就是它能够成功且长久不衰的秘密,总结起来就是:简单(基础组件)、灵活(可编程)、生态(开放开源),这套理论其实还可以在苹果 iPhone 等产品的颠覆性成功上得到验证。
典型的完整 Spring Web 应用:

利用第三方 Web 框架的 Spring 中间层应用:

远程服务使用场景:

- 4.1 Spring 的设计哲学
这是 Spring 官方文档上阐释的设计哲学,当你学习一个开发框架时,除了知道它能做什么之外,最重要的是要了解它都遵循哪些原则,下面这些就是 Spring 这套开发框架所遵循的指导原则:
- 提供不同层次的选择。Spring 可以帮助你将设计决策尽可能地延后,例如:你可以通过修改配置而不是代码来替换持久化存储提供者。这条准则对于许多基础设施的关注点或集成第三方 APIs 同样适用。
- 容纳多元化的观点。Spring 拥抱灵活性,它并不固执己见地要求事情应该怎样做,它从不同维度满足应用开发各种类型、广泛的需求。
- 保持强大的向后兼容。Spring 的版本升级会尽量避免破坏性变化,它会精心选择所支持的 JDK 和第三方库的版本,方便依赖于Spring的应用和库的维护。
- 关注 API 的设计。设计更能反映业务本质且能够在多个版本和许多年里都保持不变的 APIs,Spring 团队在这件事情上投入了很多思考和时间。
- 为代码质量设置更高的标准。Spring 框架非常注重有意义、及时更新和准确的 Javadoc,它是极少数能够宣称代码结构整洁、包之间没有循环依赖关系的项目之一。
- 5. Spring 的产品推广策略
在单体式应用时代,老兵哥所在公司也有内部开发框架,以 Spring 为基础做了封装隔离,相当于在 Spring 外面包了一层,之所以采用这种方式主要有两个原因:其一,通过封装来适配公司内部技术平台和扩展定制特定功能;其二,Spring 是开源产品,它的发展存在许多变数,为了避免它的变化对应用产生不好的影响,我们需要隔离防护层。
但现在到了云计算时代,我们不再采用这种方式了,Spring 已经发展了近十五年,开源机制允许全球开发者参与其中,这些年已经证明它是足够开放的,而且它已经成了行业事实标准。我们的框架除了供内部用户使用之外,后续还要作为云产品面向外部用户,所以必须要跟 Spring Cloud 保持兼容,这样才能借助 Spring 已有的势,否则就成了竞争对手,就像阿里近来推出了 Spring Cloud for Alibaba。
- 产品积木式标准化,从 3.x 开始 Spring 从原先整体式的产品演化为多个组件。刚开始我们的第一印象会认为 Spring 是重量级的全家桶式解决方案,但实际上它并不是全选或全不选的解决方案,用户可以只选择其中某几个组件来构建应用。
- 解决方案套餐化,就像肯德基、麦当劳和真功夫等快餐连锁企业一样,随着产品不断标准和丰富,套餐化是更好满足用户需求的必然选择。全套推广难度太大,按需组装,针对不同的用户场景提供个性化解决方案,降低用户上车难度,先让用户用上,建立连接,方便后续进一步转化。不挑用户,而是想办法解决不同用户的问题。这样更加符合用户视角,因为用户对大而全的解决方案没有直观感受,他们只关心产品能否解决目前最急迫的问题。
- 高频特性带动低频特性,某些产品特性或组件通用性更强,它们被用户使用的频次越高,那么这些特性或组件应该保持较低的利润率,或者免费,借助它们扩大用户群体规模,从而有机会宣传推广那些低频高润的特性或组件。这其实就是互联网思维,通过免费策略来做大用户量,然后再深耕用户,所以说免费其实是最贵的价格。
- 通过标准化、套餐化就可以让每个子产品独立研发和运营,包干到户,激发创造力和动力。兵分多路,多点突破,每套解决方案可以单独推广,彼此共享用户。同时,Spring 规范了定制扩展机制,团结了所有可以团结的力量,构建了一个生态联盟。我们说架构设计就是设计合作机制,Spring 优良的架构设计非常有助于合作,从而能够突破重围。开放源代码,拥抱开源趋势,消除了客户对被技术锁定的担忧。
- 6. 总结
本文主要是对 Spring 的核心技术和产品理念做了梳理,可以作为学习 Spring 的索引参考,最好的学习资料就是官方的帮助文档。这些知识点对于深入掌握 Spring 是非常有必要的,平时工作中老兵哥经常要帮同事分析定位技术问题,在它们的帮助下分析定位问题会更加游刃有余。同时,产品设计理念和运营策略对于老兵哥推广微服务框架也非常有借鉴意义,如何从零开始去推广一套应用开发框架,读者朋友们也可以考虑将这些策略运用在其他产品上。考虑到我们每个人的工作学习情况不同,平时遇到的问题也不同,本文内容无法覆盖所有人遇到的问题,欢迎大家留言提问,也欢迎关注「 IT老兵哥 」交流互动,谢谢!
本系列其他文章索引如下:Spring 核心技术与产品理念剖析(上)
Spring 核心技术与产品理念剖析【下】的更多相关文章
- Spring 核心技术与产品理念剖析(上)
IT 技术发展太快了,就像浪潮一样一波接着一波,朝你迎面扑来,稍不留神就会被巨浪卷至海底而不得翻身.我们必须要学会抓住那些不变的本质或规律,只有这样才能屹立潮头而不倒,乘风破浪,做这个巨变时代的弄潮儿 ...
- 0000 - Spring 中常用注解原理剖析
1.概述 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来 ...
- Spring 中常用注解原理剖析
前言 Spring 框架核心组件之一是 IOC,IOC 则管理 Bean 的创建和 Bean 之间的依赖注入,对于 Bean 的创建可以通过在 XML 里面使用 <bean/> 标签来配置 ...
- Spring核心技术(八)——Spring自动装载的注解
本文针对自动装载的一些注解进行描述. 基于注解的容器配置 @Required注解 @Required注解需要应用到Bean的属性的setter方法上面,如下面的例子: public class Sim ...
- Spring核心技术(六)——Spring中Bean的生命周期
前文已经描述了Bean的作用域,本文将描述Bean的一些生命周期作用,配置还有Bean的继承. 定制Bean 生命周期回调 开发者通过实现Spring的InitializeingBean和Dispos ...
- Spring核心技术(五)——Spring中Bean的作用域
前文概述了Spring的容器,Bean,以及依赖的一些信息,本文将描述一下Bean的作用域 Bean的作用域 当开发者定义Bean的时候,同时也会定义了该如何创建Bean实例.这些具体创建的过程是很重 ...
- Spring核心技术(四)——Spring的依赖及其注入(续二)
前面两篇文章描述了IoC容器中依赖的概念,包括依赖注入以及注入细节配置.本文将继续描述玩全部的依赖信息. 使用 depends-on 如果一个Bean是另一个Bean的依赖的话,通常来说这个Bean也 ...
- Spring 核心技术(3)
接上篇:Spring 核心技术(2) version 5.1.8.RELEASE 1.4 依赖 典型的企业应用程序不会只包含单个对象(或 Spring 术语中的 bean).即使是最简单的应用程序也是 ...
- Spring 核心技术(2)
接上篇:Spring 核心技术(1) version 5.1.8.RELEASE 1.3 Bean概述 Spring IoC 容器管理一个或多个bean,他们都是根据提供的配置元数据(例如 XML 中 ...
随机推荐
- phpStorm自动生成___jb_tmp___文件
把这个去掉就可以了
- 小白学 Python 爬虫(14):urllib 基础使用(四)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- C 可变参数函数的本质
C语言支持定义可变参数的函数,方法是在函数的参数列表最后加上 " ... ",代表变长的参数列表,例如: void Func(int num, ...) { } 需要注意 “... ...
- 基于iCamera测试AR0134 960p 全局快门相机模块小结
基于iCamera测试AR0134 960p 全局快门相机模块小结 首先看看此模块的特性 AR0134 全局曝光 CMOS模块 1280*960像素 5.3 V/lux-sec 摄像头模块实物靓照(上 ...
- CSS让高度百分百的方案
一般用来上下所有居中,但是这时候auto的计算是全屏像素,从而得到满屏 position: fixed; left: 0px; right: 0px; top: 0px; bottom: 0px; m ...
- js中promise解决callback回调地狱以及使用async+await异步处理的方法
1.callback回调地狱 function ajax(fn) { setTimeout(()=> { console.log('你好') fn() }, 1000) } ajax(() =& ...
- Dapr 运用之集成 Asp.Net Core Grpc 调用篇
前置条件: <Dapr 运用> 改造 ProductService 以提供 gRPC 服务 从 NuGet 或程序包管理控制台安装 gRPC 服务必须的包 Grpc.AspNetCore ...
- webpack打包出现WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. 错误
打包运行的时候出现以下错误 WARNING in configurationThe 'mode' option has not been set, webpack will fallback to ' ...
- Winform DataGridView控件数据导出EXcel
/// <summary> /// 导出Excel /// </summary> /// <param name="dgv"></para ...
- c++之基础数据类型
c++规定了在创建一个变量或者常量时,必须先要指定相应的数据类型,否发无法将变量分配给内存. 1.整型 数据类型 占用空间 取值范围 short 2字节 -2^15-2^15-1 int 4字节 -2 ...