提交 f671e1b0 编写于 作者: 沉默王二's avatar 沉默王二 💬

转岗

上级 bf73c82c
---
title: MySQL:InnoDB一棵B+树可以存放多少行数据?
shortTitle: MySQL:InnoDB一棵B+树可以存放多少行数据?
description: 1千万,2千万,或者上亿条数据?具体的答案不重要,当然肯定也不会是一个固定的数目,今天我们就一起来探讨探讨这个问题。 InnoDB是一种兼顾了高可靠性和高性能的通用存储引擎,它拥有诸多功能和特性,体系结构和工作原理也比较复杂。真要讲明白说透彻,不是一两篇博文能够实现的,也不是今…
tags:
- 优质文章
author: 清幽之地
category:
- 掘金社区
head:
- - meta
- name: keywords
content: MySQL
---
null
>参考链接:[https://juejin.cn/post/6904293886626103309](https://juejin.cn/post/6904293886626103309),整理:沉默王二
---
title: 从纠结到放过自己——2022 年终总结 - 菜狗の日常
shortTitle: 从纠结到放过自己——2022 年终总结 - 菜狗の日常
category:
- 其他网站
---
# 从纠结到放过自己——2022 年终总结
发布于 24 天前 143 次阅读
* * *
> If you miss the train I'm on
>
> You'll know that I'm gone
>
> You can hear the whistle blow
>
> A hundred miles
2022 年,距离 2017 年已相去五年,离 2021 年也有一年之远。然而就是这区区一年,产生影响之深远更要远胜先前四年。对于我个人来说,是生活方式的根本性转变,使得我不能再以学生的身份自居,而不得不站在一个“社会人”的角度去思考问题了。
早先四年,以至于工作的前半年(2021 年下半年),可谓混沌一片。即无短期目标,亦无远大志向,只想着过一日是一日。于是 2020 年下半年考研将近,并未做什么深远考虑,即选择了考研,目标院校也没经过深思熟虑,直接延续了高考失败的目标——浙大。更可笑的是,当年选择浙大的理由,在考研时早已记不清了。然浑噩三年之久,早就丧失了潜心学习的能力。于是在复习一个月高数后,学而不得的焦躁和装模作样的负疚感就让我无法继续。放弃的过程也很“顺滑”,仅仅是一个早晨的突然决定。这何尝不是一种逃避选择,选择了更擅长的代码而非科研,但仍以“迟早都要工作”的理由麻痹自己。于是就是背八股、做项目、实习找工作。后续的事情倒还算顺利,找到工作后毕业入职,并幸而在裁员大潮中得以保全,并未受过大影响。而剧变的降临,又有谁能完全不受影响,但这又是 2022 年的事了,后面会说到。
然而纵使是找到工作,仍延续之前习气难改。这或许不是一个转折关系,更像是个因果关系:正因为过于顺利,于是便没有理由去寻求改变。一个典型,也是现在最为后悔的事,就是在找到工作到毕业这段时间,大约一年有余,竟完全未学习任何新内容。彼时女朋友正在考研,那这段时间大概又可分为两个区间,即以女朋友考研初试为界:前半段每日十一点起床,接着就是去图书馆陪女朋友学习。表面上是陪伴学习,实际上大部分是在看剧和打游戏中度过。晚上则约同学或好友去酒吧,那时已不能称之为“小酌”,而可称为“酗酒”,总是到半夜方才大醉而归。后半段生活甚至现在已无甚印象,更可见颓废到何种程度,以至无标志事件可供回忆。
找工作过程的过于顺滑,更易让人目空一切。古人云“人之患在好为人师”,诚哉此言!早早结束校招,更给了以“过来人”身份说话的资本。而沉溺其中,终会使陷于此身份,从而失去前进之动力。一口一句“大佬”,已使人飘飘然,更何况有些所谓“技术群”聊天,言必称“神”,一个小小的微信群竟能封神几十位,无神论者无法接受,一神论者亦觉得不可思议。于是忽有一天感到厌倦,毕竟不能一辈子吃校招的饭(更何况我还无此饭可吃),既与我本心违背,亦不利于进步。于是痛定思痛,一天之内退掉了所有的所谓“技术群”,甚至牛客都卸载了(对不起)。然而这又是 2022 年的事情了,本身校招就只准备了三个月,无夯实的基础,更有很多运气成分,这损失的一年光阴又愈加令人惋惜了。
以上是对前四年的总结。转变大都发生在 2022 年,无论何时发生转变都乃万幸,希望悬崖勒马尤未晚矣。
工作自然无甚长期内容可说,毕竟我仅仅入职一年半,但纵使是这十几个月之经历,亦可称为风云变幻了,令我领略了拥抱变化之深刻含义。
本组事务,最初仅是为活动提供技术支持。组内分工明确,一部分负责开发框架和组件化,力图让业务需求无需特殊开发,或只需稍加定制即可满足;剩下成员则是纯业务开发,高并发细节几乎无需考虑,所有的细节已由框架处理好。原则上来说,业务组织的活动,大部分由组件化即可直接满足,业务仅需拖拖拽拽即可搭建好一个活动,无需开发的介入。仅剩其中很小一部分的活动需要特殊开发,然而即使是这一小部分,亦会消耗巨大的人力。于是本组发力于组件化功能之完善,在我入职之前,组件化已完善到,业务开发仅需配 json 而无需具体去编写定制代码,即可完成定制逻辑开发。组里框架已高度成熟化,组里分工也理所当然地接近凝固。
待我入职之时,业务开发已无需如先前巨大之人力,除非是在重大活动期间,才会增添人力以示重视,否则,一个较大的活动仅需一位业务研发去负责,如果较为熟练甚至可以同时开发两三个活动。在此背景下,我便“理所当然”地闲下来了。此时恰好,北京的一个负责 ToB 平台的组正陷于人力困扰中,向大部门请求抽调借人。于是我被选中,开始了远程开发之路。
坦言之,在公司内部,ToB 开发一般不会比 ToC 开发更受重视,对于校招生来说,ToC 业务的第一直觉,就是可以接触大流量高并发场景,但那实际上仅限业务刚起步之时。在一个已经有高度成熟框架的业务中,底层的细节已被巨大的抽象所屏蔽,在承担更重要职责时也通常会为了求稳而非求变,对框架的一点点修改都是不可控而风险巨大的,更何况还是在倒排压力下。无论什么原因,对底层做修改都是很难的,除非彻底无法满足业务需求,不得不完全推翻整个框架,而这种情况下,上级会质疑这个组存在的意义,而倾向于将新框架的开发交由其他组,除非这种对框架的升级和迁移是渐进式的而非一刀切,但这又回到了上面所说的投资产出比(ROI)上去了。
总而言之,ToC 不见得都能接触高并发,这里算是澄清这个误区。
和北京同事合作的过程是十分愉快的,整个组内氛围十分放松,不会因为你的一点错误而对你横加指责,亦无甚惩罚措施。再加上我是远程合作,上班时间可随心所欲,经常十一点半才到达工区,坐上十五分钟就去排队吃饭,接着就是午休时间,实际工作时间是从下午开始的。就这样度过了快乐的半年,我甚至以为这种生活可以一直延续,而外界那些“卷”的传闻仅仅停留在传闻的程度而已,不会真的有人这样卷。
转变来自于产品经理的变动,具体原因已不甚清晰,但结果却很奇怪。本组要放弃原本的活动业务,转而接下那个 ToB 平台作为主要业务,而原本北京那组人则集体转岗。整个交接过程混乱而冗长,这个平台年轻而苍老,年轻在于,21 年 56 双月该平台刚刚经历过一次重构,代码都很新,而苍老在于,该平台已发展了 3 年,自 19 年该平台立项以来,无数积累下来的历史逻辑,已无任何可能被完整了解,堆积起来的业务定制逻辑,即使找到当时提出的产品也无法完整地说出个所以然。与此同时,原本的部门领导,转岗到了一个新业务,令他的下属们:各组的领导,和各领导的嫡系,蠢蠢欲动。在新任部门领导尚未有所动作之时,几乎是打包似的向新业务转岗。这种情况直到新任部门领导锁住本部门转岗后才有所平息。而在此之前,本组的领导已和组内几个嫡系都已成功转岗出去了。
人员变动导致人心惶惶,整个 22 年上半年几乎没有做成什么事情。我由于提前参与平台业务,负责其中主要的两个模块的交接,然而交接后依旧是我来负责,如同左手倒右手一般。
本组的领导转岗后,一段时间内,本组领导由部门领导兼任。六月份时,部门领导提议,将原本测试内部的质量双周会扩展为产研测都要参与的技术双周会,并同时开始狠抓平台质量。这本身是一件好事,然而粗暴的执行导致了双周会偏离了原本设置的初衷。其中最令人闻风丧胆的措施,就是统计 bug 估分比。测试阶段发现的 bug 个数,比上开发和联调的天数,即作为研发开发某个需求时的 bug 估分比,由此这也被称为“bug 比人天”。这个计算方式十分简单和直观,但是似乎没有考虑到一些边界问题,例如一个很小的需求,开发联调只需要一天,那么被测出 1 个 bug,bug 估分比就达到了 1。领导们为 bug 估分比设置一些指标,以达到保证研发质量的目的,双周会上会对 bug 估分比不达标的研发进行质询,如果该研发是外包,那么他甚至会面临被清退的危险。最初这个指标被定为 1,后面逐渐收紧到 0.5,甚至 0.3。这其中当然有严抓研发质量之功劳,但更多的是,由于研测关系此前一直十分和谐,测试同学在测试过程中可能只是口头提出问题,而不会从系统提出 bug。或者在和数据同学合作的过程中,由于数据侧不关注 bug 估分比这个数据,可以将 bug 转给数据同学。这种互相“包庇”的情形最终被测试的领导发现后,严格禁止了这种行为,如果发现某个需求的 bug 过少,测试领导甚至会亲自下场测试。这无疑加剧了研测冲突。曾有一测试同学,严格按照规章办事,她测出的 bug 过多,最终直接或间接地导致了一名正式研发主动离职和一名外包研发被清退。在后期本组领导终于意识到诸多问题后,废除了这个指标,双周会上不再关注了。
然而双周会上的另一环节,则更像一场闹剧。由于本平台是个面向运营的 ToB 平台,每天都会收到来自运营同学的 oncall,大部分是咨询平台的使用方法,少部分则是由于平台 bug 导致流程无法继续进行。在双周会上,会由测试整理出周期内 oncall 来的平台问题,一个一个讨论以找到责任人和后续避免的方法。然而实际执行中,找到责任人似乎比后续避免更为重要。有些问题历史十分悠久且模糊,难以精确定位到某个人,有些问题则是产品设计问题,而通常,如果确是研发问题,测试则有连带责任,因为他们在测试阶段没能发现而导致 bug 逃逸到线上。由于各种模糊和不准确性,其中的运作空间十分大。例如研发可以把问题推给产品或者之前开发这个模块的人,而测试则可以说在测试阶段并无此问题,可能是后续需求影响甚至是研发在测试流程结束后偷偷更改代码。于是每当这个环节,产研测三方相互攻讦,反正大部分已无证据,重要的无非是否能在气势上压倒对方。有趣的是,如果某一方没有参加双周会,那么剩下两方则会默契地将问题向未参会的一方推。否则,除了确是产品设计问题外,落入下风的通常是研发,测试通常会直接质问为何要在测试结束后更改代码,而相关研发也懒于翻出 git 记录来解释。这种质问通常直接来自于测试的领导,而本组领导由于初来乍到,似乎也不太敢于抗辩。
另一个好心办坏事的例子就是 code review。code review,本意为通过在线上同时审阅代码,来发现潜在的代码逻辑问题,以保证这种逻辑问题不至逃逸到线上,最终不可收拾。可谓为测试后的最后一道放线。在平台业务尚未交至我组时,北京一组并未建立起严格的 code review 制度,代码质量由个人把控保持。本组领导初来乍到,便要求全部上线代码必须经过 code review。然而其忽略了本组之现状,即单个业务方向,可能仅有一两个一线研发直接负责,而这些业务方向下通常又有多个细分。如前文之所言,业务已膨胀到无任何研发能够完全将某个方向的细节了然于胸,而对其他模块之业务更是一知半解。然而线上或线下的 code review 通常需要邀请三到四个人,在这种业务分隔的情况下,code review 内容更偏向一些无关紧要的问题,例如一些代码风格和命名规范问题,而一些真正的逻辑漏洞则不可能被发现,使得这些问题依旧会逸至线上。而需求负责人也不得不花上个几小时,在线上或线下的会议上,来给一些可能根本就没有听懂的人,费尽口舌地去解释代码是如何满足业务需求的。
一线研发疲于应付这些意义不大的事情,于是整体研发效率不高也是可以解释的。而纵使在人力不充足的情况下,仍然要在这么小的一个组(三十人左右)实施比较严格的上下级制度,设置了一个与小组体量不太相称的中层管理机构。中层管理们通常不负责具体需求的开发,而只是管理其负责的模块下的人力分配和 code review,导致本就不富裕的人力更加紧张。而本组在人员调配上也是较为混乱的。一些同事甚至从转为平台业务开始,就一直在其下各个子方向流转,其不稳定性更加剧了对本组业务的不满。
纵使工作一地鸡毛,然亦非完全毫无收获。ToC 到 ToB 的转变,工作重点完全不同。ToC 业务中,高并发大流量场景下,如何保证业务的高可用,成了重中之重。为此目标,甚至可以丢弃一些用户请求来保证整体的可用性。这在 ToB 平台则是完全无需考虑的事情,于是关注重点更多转移到一致性上,大多数情况下,保证最终一致性,即在上下游环境不完全可靠的情况下,保障最终(可能是在多次重试后)上下游数据一致,这一般就考虑接口的幂等性;对于需要强一致性的场景,甚至需要引入分布式事务。
除此之外,技术上似乎并未有明显的进步。大都延续了先前的浅尝辄止:年初计划编写一个 RISC-V 的模拟器(emulator)。目标定的很大:要能运行 Linux,提供 VGA 输出,并最终实现为一个比较完善的 debug 平台。然而在实现 RISC-V 的一个子集,足以运行 xv6 后,这个项目就被搁置到了现在,如果不是年度总结,它可能还会一直被搁置下去。
年中基本都在交接和内卷中度过,无甚时间关注自身的技术发展。至十月时,痛感一事无成,于是开始制定计划,准备夯实“丢失的基础”,如分布式、计网和计组。于是在学了大约两个月的 6.824 后,因为疫情在床上躺了几天后,也被搁置了。
我大概是个纠结的人,一方面不满于其他人对自己的压力,另一方面又会自己给自己施加更多的压力,纵使是对一些小事,如组内分享,也会感到压力巨大,这种心理状态甚至严重影响到了我的心理和身体健康。于是在痛苦挣扎了半年,灌了自己半年的酒后,最终还是不得不和自己和解,淡化心中强加给自己的压力,不再如此争强好胜而尝试看淡一切。杜康不能使你忘掉一切,只有你自己可以。
曾有一日,在为无穷无尽的平台 oncall 淹没后,忙里偷闲来到前端处,恰逢与我合作前端同学正在改 bug。我在他身后站了一会,看他忙于在 ide 和 oncall 窗口间切换。于是问他:“你不感到烦吗”。他转头看了我一眼,说了句:“其乐无穷吧”
是啊,其乐无穷吧,不然又能如何呢?
于是,2022 年就这么过去了,沉重而轻盈。
本想着,开头那段歌词用下面这段:
> Not a shirt on my back
>
> Not a penny in my name
>
> Lord I can't go home this way
但似乎尚未落魄至此,前路虽暗淡,也可望到前路将更加暗淡,然仍心存光明。这一点光明,不期照亮前路,但求照亮自己。
> 这篇总结本计划在回家的高铁上完成,却未曾想写了三天。中间思绪万千,也可见其间文风也有较大变化,基本都与我之心境有关。从描述工作时的愤懑,到最后的坦然,这篇文章同样经历了标题所述的变化。然仍会为不忿之事而不忿,足见尚未完全放下。最终在纠结中,还是觉得不如就此停笔,令新一年的我继续去纠结,或许也是其乐无穷吧
[2022](https://ziyang.moe/article/tag/2022/) [年终总结](https://ziyang.moe/article/tag/%e5%b9%b4%e7%bb%88%e6%80%bb%e7%bb%93/)
>参考链接:[https://ziyang.moe/article/2022_final.html](https://ziyang.moe/article/2022_final.html),整理:沉默王二
---
title: 开源活动及项目推荐 | Forever Young
shortTitle: 开源活动及项目推荐 | Forever Young
description: 2022-09-04 17:09:15 准备写,预计一周内更新选择合适的开源项目怎样选择一个合适的开源项目,这个话题很大,本文仅从提升本科生和研究生做开源这个角度来聊一下这个问题。也会推荐一些项目让大家来参考、选择。当然,此文仅是我 @edengk 的一家之言,此文也尚有诸多不足之处,还请各位辩证看
tags:
- 优质文章
category:
- 其他网站
head:
- - meta
- name: keywords
content: 开源
---
之前就给球友们提过,如果能参与到一个顶级开源项目的开发,那么在校招的时候会非常加分,无论是本科阶段,还是研究生阶段。
那么今天就再给大家推荐一些顶级的开源活动以及项目。
## 实现型项目
实现型项目,主要指的是一些开发类的项目。基本上是**已经决定好了**要实现这些东西,然后提出一个议题、项目,让人来实现这些东西。
常见的比如:
xxx实现
新增xxx插件
使用xxxxx为xxxx实现xxx
基于xxxx实现xxxxx
xxxx开发
此类项目较多的活动有[中科院的暑期之夏](https://summer-ospp.ac.cn/)[Google的GSoC](https://github.com/gsoc-cn/gsoc-cn)
## 研究型项目
这些项目主要是需要人再去研究、做实验论证的一些项目
比如通过研究xxxx使得xxx的效率/性能得到提升,这些项目一般**要先研究然后再去实现**
对xxxx进行优化
xxxxx优化
优化xxxxxx算法
改进xxxx算法
此类项目较多的活动有[计算机学会的开源夏令营GLCC](https://www.gitlink.org.cn/glcc)
## 本科生
相对于研究生来说,绝大多数本科生有相对自由的日常时间,以及寒暑假可以自由支配。有自己可以支配的时间就代表着可以去做自己喜欢、想要做的事。
如果你是一个还没接触过开源社区、开源文化的球友,可以尝试参与一下开源。
初步参与开源的球友,可以试着参加一下各个组织举办的开源活动,开源活动有很多优点,这里列举两个。
第一个是不受地域限制:
比如[中科院的暑期之夏](https://summer-ospp.ac.cn/)[计算机学会的开源夏令营GLCC](https://www.gitlink.org.cn/glcc)[Google的GSoC](https://github.com/gsoc-cn/gsoc-cn),基本上都是远程的。球友们完全可以在一个二三线的城市的学校校园里,去参加这种全国甚至全球性的开源活动。
第二个是它可以为我们背书:
开源本身就是开放的,大家都可以看到我做了什么事,整个社区都是我们的见证人。包括以后我们写到简历里,参加了什么样的开源项目、对社区做了什么样的贡献,这些都是有目共睹的。
所以开源经历本身的含金量也是非常不错的。
如果你在一个很知名的开源社区做了很多突出的贡献,这个背书的效果是远比一般的中小公司要好上不少的。
志向远大,想要进顶级大厂的,拿 ssp offer 的球友一定要冲一把。
如果你喜欢研究分布式云原生,那么[CNCF基金会](https://www.cncf.io/)下面的项目会更适合你
如果你喜欢研究数据库,InfluxDB、TiDB........各种各样的数据库欢迎你
如果你擅长Go,上面CNCF基金会欢迎你
如果你擅长Java,Apache基金会下N个顶级项目欢迎你
如果你擅长C/C++,[GSoC2022](https://github.com/erdengk/gsoc-analyse/blob/master/docs/en/gsoc/GSoC2022/c.md) 中100+个项目欢迎你
## 研究生
二哥没有经历过研究生阶段,所以这部分的经验是来自一个读者。
在此处,我们先将研究生导师分成四类,
1. 第一类是导师、课题组方向与自己方向一致的
2. 第二类是导师、课题组方向与自己不一样还要push自己的
3. 第三类是导师、课题组方向与自己不一样但不强求学生的
4. 第四类是导师放养的
研究生的开题,必须要“创新”。
> 创新可以理解为
>
> 用某种新的方式解决了一个很细节的问题
>
> 偏实践类型的就是
>
> 基于xxxxxxx场景下缓存的研究与设计
>
> 或者研究出一个“新”的算法 或对某个算法的优化
>
> 基于xxx-xx-xxx的算法研究
>
> 基于分布式关系型数据库的xxx算法优化
对于导师是第二类、第三类的球友,可以通过参加开源活动,来获得额外的机会来做自己想做的东西。
目前体量比较大的主要是三个活动,
- [中科院的暑期之夏](https://summer-ospp.ac.cn/)
- [计算机学会的开源夏令营GLCC](https://www.gitlink.org.cn/glcc)
- [Google的GSoC](https://github.com/gsoc-cn/gsoc-cn)
暑期之夏、GSoC中的项目更多的是实现型项目,在GLCC中也有不少的研究型项目,如果做的好也会有很大很大的收获。
* 没有其他顾虑的球友可以随意选择自己喜欢的项目
* 需要**自己考虑**毕业问题/想自己研究喜欢的方向的球友可以考虑做一些偏研究性的项目以此开题/毕业
* 所有球友都可以通过参加开源来提升自己的编程功底、拓展社交圈子、增加就业机会。
>参考链接:[https://erdengk.top/archives/kai-yuan-huo-dong-ji-xiang-mu-tui-jian](https://erdengk.top/archives/kai-yuan-huo-dong-ji-xiang-mu-tui-jian)
---
title: 我的硕士前半生 | Forever Young
shortTitle: 我的硕士前半生 | Forever Young
description: 本篇文章属于随笔类,它可能无法对你起到直接帮助,它只是我这个普通学生一年半以来的一些足迹与思考。它可能更适合大二,研0研一的同学查看。本文首发于我的个人博客 Forever Young我的本科像硕士,有实验室有工位,桌子超级大,有老师带有学长可以问。我的硕士像本科,没有实验室,工位真的是公共座位,导
tags:
- 优质文章
category:
- 其他网站
head:
- - meta
- name: keywords
content: 年终总结
---
> [二哥的编程星球](https://mp.weixin.qq.com/s/hXXBTPPkFj2VMg_GXqn4EA)已经有 **1500 多名** 球友加入了,如果你也需要一个良好的学习氛围,[戳链接](https://mp.weixin.qq.com/s/CljCSezUgoBXb-T9wbIGww)加入我们吧!这是一个编程学习指南+ Java 项目实战+ LeetCode 刷题的私密圈子,你可以阅读星球专栏、向二哥提问、帮你制定学习计划、和球友一起打卡成长,冲冲冲。
大家好,我是二哥呀。
在朋友圈看到一位读者写的这篇“我的硕士前半生”,感觉应该会对大家有较大的启发,于是分享出来,希望对大家有一些帮助🤔。
PS:这位读者拿到了美团、百度、网易、滴滴、B站等大厂的日常实习offer,他是如何做到的呢?
## 21年9月 迷茫
研一刚入学还是有些迷茫的,这种迷茫不是那种无头苍蝇式的迷茫,大体方向是准备实习找工作,落实到具体细节却并没有做好
先是没有吸取大学的经验,都准备去找互联网工作了,竟然还准备去参加班干部选举(幸亏没选上😂,要不然就被学校绑死了
然后发现了学校政策其实不是那么完善,奖学金和国奖有漏洞,花时间和钱就一定能拿,但这样拿了又有什么意义
和本科实验室的阿里学长聊了下该学什么,简单规划路线后就开始学了
## 21年11月 GSoC
### 缘起
准备过程说起来也很简单,就是正常的学,刷题、八股。
忘记了是因为什么想起了GSoC,算是为了圆梦吧,第一次认识它也是在知乎,来自那篇广为流传的文章:Google 编程之夏(GSoC):海量优质项目,丰厚报酬,你竟然还不知道?
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-7795b016-e2dd-4dda-bd96-0b33a583a916.png)
>二哥:我之前给球友们有推荐过,不同于一般的比赛,非常的酷。
### 查找资料
确定参加后就开始查找资料,国内国外中文英文资料都在搜。
因为官网的搜索并不是很好用,我的主要技术栈是 Java,于是想从一些Java社区入手,在官网上搜索 Java,结果会连 Javascript 的社区也一并搜索出来,我觉得这很不方便,于是将官网2021年的项目信息爬下来,存到数据库里。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-b3bed841-fa05-4c2b-b0dc-ff44dfff274c.png)
然后用 SpringBoot 读取出来做些简单数据处理输出到MD文件中,也就产生了早期的 gsoc-analyse 项目,本意是为了更好的查找符合自己技术栈的项目。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-198ec1e2-ed1f-4e94-99d5-3b90f4d39990.png)
### Casbin 奇遇
gsoc-cn有一个gitter群(一个聊天室,可以查看很久之前的信息),我查找资料的时候,翻看了近2年的所有聊天记录,发现了 Casbin 的罗老师有在收人, 我去加了群,也给罗老师发了简历。
因为我当时比现在更菜,简历上也没什么能看的,硕士还写了个电子信息,让罗老师误以为是 EE (*Electronic Engineering* ) 而不是 CS (*Computer Science* ),这也给我提了个醒,看简历的人不一定和写简历的人有相同的知识背景,只是大致相等,对于部分可能出现误会的地方应该标识/解释清楚。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-cbaf3e81-8e46-4448-9665-9894f23584f8.png)
然后我又和罗老师围绕着我简历交流了一些其他问题(后来才知道罗老师是两届GSoC学生,北大博士,跪了
最后罗老师还是友善的给了建议,其实一直知道自己菜,但没能完全找到自己的弱点。如果是想一直靠技术吃饭,但活到老学到老是必然的。即时是想先进个好点的厂打工,知识的深度也是要远比广度重要的。
### 21年11月 申请维护GSoC QQ群
我感觉gitter上交流没有群聊方便,gsoc-cn之前的QQ群也没人维护了,我建立了新的QQ群,并发到Gitter上,又在GitHup上的GSoC-CN仓库上提交了issue,申请把QQ群加入到他们的readme中,让更多的人加入到群里。
仓库的reviewer也同意了我的请求,让我提交pr,然后快速的学习了下pr之类的操作提交了第一个pr。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-e21c3f8a-cb84-4eab-8f1f-c74929c076fb.png)
算是迈出了个人开源的一小步
### 22年4月 前期准备及提交申请
大致就是我先选了一个社区,社区不是很活跃(一个博士课题组的社区,他们都很忙,一个pr得审好久好久),我没有收到正反馈以及不知道能做些什么,也就放弃了这个社区。
也是运气使然,我后来的mentor 在群里发布了社区的项目,我一开始不知道他是mentor,先加了他微信,看了社区的项目,发现有一个是自己还敢尝试一下的,然后在github上发现了项目导师的联系方式
巧的是,我已经加了他的微信(在不了解项目时加了联系方式,后面选的项目刚好是他当导师😂
因为之前看了很多经验贴,建议不要在没了解过项目的前提下和导师交流
后面也就开始了贡献,在社区里解决了第一个 good first issue 后初步了解了项目,
后面开始解决其他问题时,也遇到了愿意帮忙解决问题的贡献者(Jooks 、Y哥、福哥 .....
(算是另一种意义上的组>部门>公司了)
中间也是提交了一部分pr
然后花了一周每天2-3点睡,学习了项目中用到的另一个东西
晚上疯狂用GitHub 的 action 做实验,最后做出了一个demo
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-93f80a9f-8fc5-4411-9bd8-41660b11da81.png)
期间也和项目mentor一直在讨论项目细节,mentor也给了很多建议
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-d6156f48-72d4-4b95-aa85-e4c219df78ca.png)
或许是之前写保研申请书的时候经验起了作用,再加上看了很多前辈的申请书,proposal 中加了一些花里胡哨的图、apache要求的内容,mentor reveiw之后还夸了我的 proposal (开心~
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-8c489b1a-7bf4-4fb8-8c49-df5082bfb815.png)
gsoc是支持一个人申请三个项目,我一直在这个项目上探索,最后也就申请了这一个项目
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-5a635f72-db85-495d-bd4b-1bf7f1c21531.png)
### 22年5月 GSoC-CN社群分享会
建立QQ群之后,因为有gsoc-cn的引流,也吸引了很多小伙伴
比如后来我们一起举办分享会的 cheverjohn, 彼时他还在 Apache Apisix 实习,也认识很多开源大佬,和他交流后也了解到了很多关于Apache 基金会的东西,然后我们就在群里举办了 GSoC-CN的第一个分享会,是由 Skywalking 的 Committer 江前辈 (Apache SkyWalking Committer | Google Summer of Code 2021 Student | pingcap intern )主讲的 关于OSPP 的 分享会。
### 侥幸中选
分享会之后不久,就是 GSoC 开奖了,规则限制导师不能提前透露相关信息,我也没有去问,公布名单的时间是国内时间的晚上两点,我还记得那天晚上我开了个腾讯会议,群里很多人一起在那等待,2点过了一会等到了第一封邮件。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-266d9854-71f2-4650-9c4c-b0bc40e454a1.png)
## 22年6月 开题与GLCC
这里首先要感谢我的导师,没有他的“支持”,我也不能这么自由。
我导师应该是个反卷达人了,也不加班,平时自己接点项目自己做,学生想做可以做,不想做也没事,工程领域里的他全都会,前后端嵌入式人工智能都会
在开题这件事上,他允许我自己去探索,即使他自己也不懂我当时想做的云原生领域。
我一开始不懂为什么不能直接放手学生去做自己想做的,后来和罗老师交流才明白导师能让我做是多么不容易。
对于研究生来收,一个组通常都是做同一个细分方向的,如果有个学生要做其他领域的东西,对于导师来说,这个东西他也不懂,也就很难给出指导,所以一般不会允许自己的学生去做其他方向。
后来和导师商量着先自己去探索,如果探索出了些东西,很好。如果没有,那就需要在他指导下做点东西。(毕业还是要毕业的,兴趣不能当饭吃
### 学习分布式相关知识
因为对分布式比较感兴趣,之前看谷歌的三驾马车也是囫囵吞枣的阅读完了,没有真正的学懂它们。
然后从谷歌、知乎、GitHub、各种社区搜寻分布式的资料
得益于谷歌的搜索及排名算法,我找到了很多不错的资料和博客
然后就是自己看论文,看项目代码
花了几周,学了一些基础知识,自己太菜了,没人带没能深入到具体的某个方向
后续因为在GLCC上看到了感觉合适的项目,和校内导师商量之后觉得可以作为毕设,就去申请,因为自己没申请上,用一个自己感兴趣的东西作为毕设的想法也就泡汤了 😭
### GLCC-开始-结束
彼时,计算机学会的 GLCC 刚开放申请,我也申请了一个项目,分布式相关的,也和导师做了一些交流,可惜,太菜了,没能获得社区导师的认可。
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-ba67879f-fa53-43d8-a37c-d3e9a1419665.png)
路漫漫其修远兮,吾将上下而求索
## 22年8月 日常实习求职实录
### 投递&面试
花了一个月面试
小厂、中厂、大厂,除了字节约面拒了以外,其他约面的都面完了
因为之前花时间入门了一下分布式的东西,再加上当时已经写了 这篇博客,所以将一些分布式的东西也写在简历上,我觉得是运气加持,遇到了一些比较match的面试官,他们有的懂分布式,就会问一些问题,这些问题,我有的会,有的以前没思考,借用他们的提问,我完善了我的八股串,后期熟练之后可以不间断输出自己的理解
有的不懂,那我会从其他方面聊一些入门知识,聊着聊着就耗完了面试时间,做道算法题,这场比试就结束了。
可能是我唬住了面试官,除了一开始投的某八股厂,剩下的面试都过了(以及一堆面完之后没发感谢信也没发后续流程的公司)
### Offer 选择--人生处处CAP
靠着8分运气,也拿到了一些offer,大厂、中厂、技术厂、小厂外包、传统公司都有,
选择起来说简单也简单,自己学历不够好,选个大厂学学项目规范,让简历看起来好看一些。
然后就剩下了几家了,但都是卧龙凤雏,base、部门、公司 每个offer都欠一样,或许人生处处CAP吧
## 23年1月 认识了更多大佬
找日常实习时,认识了也在准备日常实习的 ConquerJ (现在是titok的实习生),后来又认识了更多有实习/准备找实习的同学。
### 给巨佬们跪了
目前有:
获得 N个 SSP 算法岗 offer 23届佬哥 | N个 SPP offer 佬哥们 |23届 阿里P6 佬哥 |top +米哈游 佬哥
top+顶会+大厂实习佬哥 | 985+NUS 佬哥 | UCLA + 华尔街量化佬哥
Apache 某社区 Committer 佬哥 | CNCF 某社区 Reviewer 佬哥
本科发顶会论文佬哥 |国内顶尖实验室佬哥 .......
**“我经常被他们嘲笑,因为我有一个offer是sp”**
**来看看部分佬哥们的自我介绍:**
**23届 11 个算法 SSP Offer**
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-8b9e5a74-5493-4fe7-9bf7-02ff33dbdbcd.jpg)
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-bd583842-e881-486b-a710-1bef835804b2.png)
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/nice-article/other-wodssqbsforeveryoung-067d79e6-46bf-495b-a411-b678a3358988.png)
## 最后
### 回首才发现走出去了很远
如同乔帮主在斯坦福演讲中所讲的
> 当然,当时的我没有办法把这些点点滴滴连接起来,但当我从这回头看时,一切都变的清清楚楚。
>
> 的确如此,没有人可以未卜先知,把自己所学到的东西连接在一起,我们只能在回首的时候,发现这些是如何改变现在的自己的。
>
> 所以,你必须要有这样一种信念,那就是你现在的所有点滴,都会在未来的某一天连接起来,改变你的人生。
>
> 你必须要有一种信念,相信胆识,命运,生活,轮回,无论什么都好。
>
> 因为通过这些信念,会带给你遵从内心的勇气。
>
> 即使你内心的声音让你走一条人迹罕至的路,这些信念也会给你勇气,然后改变一切。
当时因为感兴趣而去准备GSoC,去维护QQ群,去举办活动,才能在后面认识了很多前辈,进入了另一个圈子。
GSoC的活动,或许并没有让我的编程水平有突飞猛进式的提升,但通过参与它,我有了勇气去尝试新的未知的东西,这是最大的收获。也因为参与GSoC,我认识了社区里的前辈,后期投递实习时拿到了很多内推机会。
当时因为兴趣去学的分布式基础知识,没能在毕业设计中直接用到,但在后面面试中用到了很多,也获得一些面试机会,获得一些offer。
当时因为喜欢交流,加入了[二哥的编程星球](https://mp.weixin.qq.com/s/CljCSezUgoBXb-T9wbIGww),才能在后来认识了八股战神&放弃直博复旦的冰冰同学,认识了三个月上岸的titok的凡哥.......
没有人可以未卜先知,我们只能基于当前时间之前的经验做出选择
直到回首望去,所有的脚步都会被串联起来,指向你现在的位置
### Follow your heart
不一定大公司就适合每一个人,可能它要求实习生日报,正式员工okr,双月okr,可能每天要开站会,可能要早上8点上班,也可能支持永久远程。
公司有很多很多,但我们很难知道自己想要什么。
### 读书好 多读书 读好书
大学时人傻,没有好好利用好时间
读研后,因为睡眠一直不好,控制变量做了些实验后觉得是睡前没有平复心情
然后开始看书,小说、传记、技术书都看
学校的图书馆很好,一次可以借很多本,借完放床头,睡前开始看,看个1h再睡,睡眠改善了很多。
> 在这个信息纷杂的年代,读书可以帮助我们更好的思考,
很多经典技术书也是非常值得一看的,还记得面试某游戏厂时遇到的一个问题,最近有看什么书吗?
当时在看DDIA,刚读完吴军博士的软能力,对着面试官就是一顿输出😂
多读一些经典书、好书,总会派上用场的
>参考链接:[https://erdengk.top/archives/wo-de-shuo-shi-qian-ban-sheng](https://erdengk.top/archives/wo-de-shuo-shi-qian-ban-sheng),整理:沉默王二
---
title: What - 什么是依赖注入?
shortTitle: What - 什么是依赖注入?
author: dingtingli
category:
- 微信公众号
---
当面对复杂问题时,我们常常无从下手,难以找到明确的方向。此时,我通常使用 WWH 方法:What——搞清问题所在;Why——分析问题根本原因、How——如何解决问题。
所以就**这个系列叫做 **WWH** ,我会把平时遇到的技术问题和思考整理到这里。**
今天,我们来看看系列的第二篇文章:**What - 什么是依赖注入💉?**
**关注我的公众号“dingtingli-pub”,并回复「依赖注入」,还会给大家提供一份简单的依赖注入框架源码**,供大家学习。
这个系列之前的文章:
1. [Why - 为什么说 JavaScript 更像一门编译型语言](http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454608234&idx=1&sn=5b2b7c62d18f01ce5dfa7607bc86a12b&chksm=fbf0b331cc873a275a5f3d42081549feb668e9d1beea7ce78125c0a547728a9cb262ff266194&scene=21#wechat_redirect)
* * *
当我们编写 Web 后端代码的时候,会用到这样的代码:
```
class A {     private IB _b;     public A(IB b){         _b = b;     }     public void MethodA(){         _b.MethodB();     } }
```
如果你跟我第一次的感觉相同,可能也会存在这样的困惑:
在 `Class A` 中没有任何地方 new `Class B` 的实例,但是运行的时候,`MethodA` 中的变量 `_b` 已经是 `Class B` 的一个实例了,为什么会这样?
今天我们就带着疑问,**了解一下依赖注入的来龙去脉**
文章从依赖注入的历史出发,分为三个部分:
1. **依赖倒置原则**
2. **控制反转**
3. **依赖注入**
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFRq9AZn4we7r4K5pYgEh3OTue7jH6oX8P9hmzF7k2FamNr4mibpWMz4g/640?wx_fmt=jpeg)
依赖注入发展历史
## 1.依赖倒置原则
依赖倒置原则(DIP Dependency Inversion Principle)
在没有依赖注入的情况下,如果 `Class A` 调用了 `Class B` 的方法,这就意味着 `Class A` 依赖于 `Class B`。换句话说,在编译时 `Class A` 将取决于 `Class B`
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFatncx75Tqrb3grIzOI32pqAS0DmBM39NGcACWEqQlcPe5PKb7Iprkg/640?wx_fmt=jpeg)
直接依赖的编译情况
代码可以这么编写:
```
class A {     private B b;     public A(){         b = new B();     }     public void MethodA(){         b.MethodB();     } }
```
在 90 年代的时候,代码差不多都是这么写的。这样的代码有什么问题吗?
为了准确地回答这个问题,让我们回到 1995 年。“Bob 大叔”(Robert C. Martin)当年提出了——**依赖倒置原则**
这个原则有以下两个定义:
1. **高层模块不应该依赖于低层模块,二者都应该依赖于抽象。**
2. **抽象不应该依赖于细节,细节应该依赖于抽象。**
上面的代码很明显不符合这个原则。那么**怎样才算能符合这个原则?**
### 依赖倒置原则示例
我们来看看 “Bob 大叔” 在他的著作《敏捷软件开发,原则、模式与实践 C# 版》中的一个示例,来深入理解这个原则的具体含义。
假设有一个控制电水壶(Kettle)温度调节器的软件,该软件可以从一个 I/O 通道中读取当前的温度,并通过向另一个 I/O 通道发送指令来操作电水壶打开或者关闭。
调节器软件将电水壶的温度控制在一个范围(最低温度 和 最高温度之间)。当温度低于最低温度(minTemp)时,就发送指令打开(Turn On)电水壶。当温度高于最高温度(maxTemp)时,就发送指令关闭(Turn Off)电水壶。
根据上述需求,代码可以这样写:
```
//读取温度的 I/O 通道 const byte TERMOMETER = 0x86;  //操作电水壶开关的 I/O 通道 const byte KETTLE = 0x87;  // 开电水壶的指令 const byte TURNON = 1;  //关电水壶的指令 const byte TURNOFF = 0;  //温度调节器函数 void Regulate(double minTemp, double maxTemp) {     for(;;)     {         //当温度高于最低温度时,就等待 1 秒中,继续循环。         while(in(TERMOMETER) > minTemp)             wait(1);         //否则就发送指令打开电水壶。         out(KETTLE,TURNON);         //当温度低于最高温度时,就等待 1 秒中,继续循环。         while(in(TERMOMETER) < maxTemp)             wait(1);         //否则就发送指令关闭电水壶。         out(KETTLE,TURNOFF);     } }
```
整个函数的高层意图非常清晰,但是实现的代码中包括了许多底层的细节,`in` 和 `out` 函数都是系统底层函数。
如果其他类型的加热器(Heater)也有同样的调节温度需求,这段代码会因为包括了电水壶的**底层细节无法被重用**
如何修改这段代码让它可以重用?这时候就可以使用依赖倒置原则。
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFT3PicFGPqj65icdDjHt4xkobVPHoibY4fXI6m8ydStha1U6nVc19FD9KQ/640?wx_fmt=jpeg)
使用依赖倒置的调节器函数
在图中,可以看到 Regulate 调节器函数接受了两个接口参数:IThermometer 接口可以读取(Read)温度;IHeater 接口可以打开(TurnOn)或者关闭(TurnOff)加热器。
接口的定义和 Regulate 调节器函数都属于高层模块,函数只需要知道着这两个接口,跟具体加热器的实现细节无关。
所有的加热器只需实现这两个接口就可以,这些接口的实现属于底层模块。
这就是依赖关系倒置,高层的 Regulate 调节器函数,不再依赖任何加热器的底层细节,函数本身有了很好的可用性。
最终 Regulate 调节器函数可以写成下面这样:
```
void Regulate(IThermometer t, IHeater h,
        double minTemp, double maxTemp) {     for(;;)     {         while(t.Read() > minTemp)             wait(1);         h.TurnOn();         while(t.Read() > maxTemp)             wait(1);         h.TurnOff();     } }
```
### 使用依赖倒置原则优化代码
依赖倒置原则,不仅解释了为什么之前代码的写法不好,而且提出了解决方案。
让我们再次回到之前的例子中:
代码 1 **直接依赖**
```
class A {     private B b;     public A(){         b = new B();     }     public void MethodA(){         b.MethodB();     } } class B {     public void MethodB(){         //code of method.     } }
```
之前已经提到,在这段代码中 `Class A` 依赖于 `Class B`。如果 `Class A` 是高层模块,如何让 `Class A` 不依赖于 `Class B`
根据依赖倒置原则,我们可以让 `Class A` 依赖于 `Class B` 的抽象 `IB`
代码 2 **依赖倒置**
```
class A {     public void MethodA(IB b){         b.MethodB();     } } interface IB {     void MethodB(); } class B : IB {     public void MethodB(){         //code of method.     } }
```
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFWveAvkv5xc8ZACdw4bxjHicS4aZ0ouUicicIREcSugOOPAjKvvNu7Q4gA/640?wx_fmt=jpeg)
依赖倒置的编译情况
此时,`Class A` 和 `Class B` 的**依赖关系反转**了。
`Class A` 和接口 `IB` 属于高层模块,`Class B` 作为接口 `IB` 的实现属于底层模块。
但是想要调用 `Class A` 中的 `MethodA`,应用程序仍然需要先 new 一个 `Class B` 的实例。
```
class Test {     static void Main(){         A a = new A();         B b = new B();         a.MethodA(b);     } }
```
这样的调用关系,在编译时 `Class A` 依赖于抽象 `IB`;在运行时,实例 `a` 仍然直接调用了实例 `b`,所以应用程序需要事先准备好 `Class B` 的实例 `b`
这跟我们说的依赖注入有什么关系?让我们带着这个疑问,先进入下一个概念——控制反转 (IoC Inversion of Control)。
## 2\. 控制反转
控制反转 (IoC Inversion of Control)
### 直接依赖和依赖倒置运行时的情况
我们回过头来,再看看之前的两段代码。
代码 1 **直接依赖**
```
class A {     private B b;     public A(){         b = new B();     }     public void MethodA(){         b.MethodB();     } } class B {     public void MethodB(){         //code of method.     } }
```
第一段代码使用了直接依赖的方式,`Class A` 依赖于 `Class B`**编译时依赖关系顺着运行时执行的方向流动,二者方向是一致的。**
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFvhERr63pNY5iaQR0PbbmicPZiceiaPIBMRQWmv0uEqGNRc6IvgTACicnXuA/640?wx_fmt=jpeg)
直接依赖编译和运行时的情况
代码 2 **依赖倒置**
```
class A {     public void MethodA(IB b){         b.MethodB();     } } interface IB {     void MethodB(); } class B : IB {     public void MethodB(){         //code of method.     } }
```
第二段代码使用了依赖倒置原则,使得**代码在编译阶段的依赖关系发生了反转**`Class A` 在编译时可以调用 `Class B` 的抽象 `IB` 上的方法。而在运行时,`Class A` 的实例仍然直接调用 `Class B` 的实例。
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFojQ0CU7fgItEWa68bfOq1ZAKAzmsuiau6eGGCnbcoUrBswqJwZhFVkA/640?wx_fmt=jpeg)
依赖倒置编译和运行时的情况
**在代码的运行阶段,这两段代码的执行流程是一致的。**
因为,**在传统的面向对象程序中,执行的代码(主函数)需要先实例化对象、再调用方法,这样代码才能继续执行。**
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFib0zZYicVddjIvxfxSUH6ESHI1LaSL17AUGlzTq0SaevFjKMwWUdT5icA/640?wx_fmt=jpeg)
直接依赖 VS 依赖倒置
### 控制反转介绍
我们回过头来,看看文章最开始使用的代码示例。
代码 3 **控制反转**
```
class A {     private IB _b;     public A(IB b){         _b = b;     }     public void MethodA(){         _b.MethodB();     } } interface IB {     void MethodB(); } class B : IB {     public void MethodB(){         //code of method.     } }
```
代码 3 控制反转和代码 2 依赖倒置的结构很类似,所以,很明显代码 3 **控制反转也是符合依赖倒置原则的**
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFKwC4rkmA1HvfGKbb0m39putAh7vrIVrpoc3GP8ricTmkOMMO2jiaOMhQ/640?wx_fmt=jpeg)
依赖倒置 VS 控制反转
但这两段代码的使用还是不一样,在使用代码 3 控制反转的项目中,开发人员不需要编写任何实例化 Class B 的代码。
为什么会这样?这时就必须引入控制反转 (IoC Inversion of Control)概念了。
### 控制反转的概念
**控制反转的主要思想是:有一个独立的框架,它可以获得接口 `IB` 合适的实现类 `Class B`,并主动创建这个类的实例,再赋值给 `Class A` 类的一个字段 `_b`。**
如下图所示:
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFU4XCAicxiabMrgnOIjd7ApgibiblYtbIlUdu1kA22YSBdwiaS0otjFagMPQ/640?wx_fmt=jpeg)
控制反转的运行时的情况
此时,**程序执行的控制流程(先实例化对象、再调用方法),就从应用程序本身转移到了 IoC 框架中**。也就是说,程序的主要控制者发生了反转,从应用程序变成了 IoC 框架。
从上面的介绍可以看出,框架的一个重要特征是:**用户为框架定义的方法,经常会从框架本身,而不是从用户的应用程序代码中调用。**
**这种控制权的倒置有时被称为好莱坞原则:"不要调用我们,我们会调用你(Don't call me; I'll call you.)"。**
在协调和安排应用活动的顺序方面,框架往往扮演着主程序的角色。这种控制的倒置使得框架有能力作为可扩展的骨架。
### 控制反转的示例
带着上面的理论,我们再来看看 代码 3 控制反转中的代码片段:
```
class A {     private IB _b;     public A(IB b){         _b = b;     }     public void MethodA(){         _b.MethodB();     } }
```
代码中,为框架定义的方法——构造函数 `public A(IB b)` ,会被框架调用而不是应用程序本身调用。
这就是为什么我们在项目中看不到任何调用这个构造函数的原因。
控制反转框架在运行时调用了 `Class A` 的构造函数,发现参数需要 `IB` 接口,就找到了接口 `IB` 合适的实现类 `Class B`,然后创建了`Class B` 的实例,最后赋值给构造函数的参数。在这里,**程序执行的控制流程完全发生了转变,从应用程序转移到了控制反转框架中。**
控制反转的发展也经历了很长时间的迭代:
从 1983 年,Richard E. Sweet 提出好莱坞原则开始;到 1998 年,随着 Java Apache 服务器框架的提出,Stefano Mazzocchi 将控制反转作为框架的主要驱动设计原则之一,普及了这个概念;最后,在 2003 年,Spring、PicoContainer 等框架纷纷实现了控制反转。最终才有了文章最开始展示的那种类型的代码。
## 3\. 依赖注入
依赖注入(DI Dependency Injection)
说了半天,我们还没有提及文章标题中的名词——依赖注入。
2004 年,Martin Fowler 在他的文章《控制反转容器&依赖注入模式》首次提出了依赖注入这个名词。
文章中指出,**控制反转这个词太宽泛,并不能很好地解释这个框架的具体实现。作者和 IoC 爱好者们商讨出了一个新的名称:依赖注入(DI Dependency Injection)。**
这个名词很形象地解释了控制反转在运行时发生了什么。比如我们之前的代码 3 中,在运行时,构造函数 `public A(IB b)` 需要接口 `IB` 的一个实例,此时框架就像是给函数打针一样,注入了 `Class B` 的实例。
下面这幅漫画生动地展现了用户的使用感受。
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFLfGiaByw8GXDMpzacC1UsbqjrQzZb18tT4PjKhJU5uyiaM6Dpf1KO03Q/640?wx_fmt=jpeg)
依赖注入漫画
**打个比方,包饺子的时候我们不需要确定具体是什么馅,只管包就行了,在吃饺子的时候,我说想吃韭菜鸡蛋馅的饺子,这时候就有人用针管给我的饺子注入韭菜鸡蛋馅。**
## 4\. 历史演变过程
从上面的描述中我们可以看到,依赖倒置原则是一个软件设计原则,而使用了控制反转的代码都符合这一原则。
**控制反转框架,将程序执行的控制流程从应用程序转移到了框架中。最终使用的感觉就是,开发者在代码中所依赖的对象,会在运行的时候直接注入到相应的方法中去,所以就有了一个新名词——依赖注入。**
整个技术的演变历程如下:
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHL1UhkNWAibOlJqInibw9KJicFRq9AZn4we7r4K5pYgEh3OTue7jH6oX8P9hmzF7k2FamNr4mibpWMz4g/640?wx_fmt=jpeg)
依赖注入发展历史
我们现在明白了依赖倒置设计原则和控制反转框架的功能,你不觉得控制反转框架很神奇,它到底是如何实现这些功能的呢?
**关注我的公众号“dingtingli-pub”,并回复「依赖注入」,提供一份源代码,大家可以详细地了解这些神奇的功能是如何实现的。**
**
![](https://mmbiz.qpic.cn/sz_mmbiz_jpg/FePLEP26kHKMviaiawjFUXE71lZkHR5xf1GdHb3cedw6O5onricJIMawslyoaJicOeMyyJlAjOyFiadXIzFyx0sQHlA/640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1)
**
* * *
所有笔记的初稿也已经发布在 github 上,大家可以直接访问:
https://github.com/dingtingli/
**喜欢本篇文章,记得动动小手点个****在看↓↓**
>参考链接:[https://mp.weixin.qq.com/s/9l-yTmin_nLffnMCvZwbmg](https://mp.weixin.qq.com/s/9l-yTmin_nLffnMCvZwbmg),出处:dingtingli,整理:沉默王二
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册