«
如何理解 Spring 当中的 Bean?

时间:2024-8   


1. spring容器就是个hashmap

  1. 前置处理器就是准备好实例化类的条件

  2. 后置处理器就是把类按第2步的条件实例化以后放进hashmap,name或者你指定的名字是key,实例就是value。这个value也就是实例,就是你问的bean,跟你手动new出来的没有本质区别

4. 依赖注入就是把hashmap里的类实例用name拿出来用

  1. aop就是允许在hashmap里面的实例使用的时候,在方法开始,进行,结束的时间点上搞一个回调函数

  2. 自定义starter就是在springBootApplication实例化的时候把指定目录下配置的类也放到前置处理器等待实例化

  3. 所谓观察者模式也只不过是在第6步的实例里面给一个监听器,监听指定事件的发生罢了,你完全可以自己实现listener搞一个监听器

  4. 所谓的什么几级缓存,也不过就是解决实例化的时候,AB类互相依赖的问题,你其实只需要知道先做一个A的引用给B,再实例化B,再实例化A就完了

  5. 所谓springcloud也只是微服务思想的一种实现,无非就是统一网关注册中心配置中心服务通信限流熔断而已,说穿了也就那样,没什么神秘的

其实spring捅破天也就这么些要点,其他的细节不过只是查查百度的事,这些基本思想闹明白了方向就不会错,无非是针对各种情况做得代码细致点,但大抵逃不出这几样,别被名词吓着。

打个断点跑一边springboot的启动流程,该知道的就都知道了,你甚至可以自己做一个spring出来,顶多功能没那么强大,但意思就是那么个意思

———————————分割线

好像看的人不少,那再附赠一个mysql的吧。

很多人觉得mysql好麻烦,b+树看不懂,索引搞不清,其实也简单

  1. mysql存储数据的基本单元是名为page的数据结构,缺省状态每个page允许16kb的空间

  2. page就是一个增强的hashmap,它包括这一页内部数据的key和value,key就是我们建表时的主键,value就是那一行真实数据。除此以外,page还包括指向前一个和后一个page的指针,包括一个自己这个page从哪个真实数据的主键开始的记录

  3. 因为一个page只有16kb对吧,随着数据越来越多,那page也越来越多对吧,即使page告诉你它从哪个索引开始,你查也要遍历,不就慢了吗,所以我们需要一个page来管理这些page,就像hashmap一样用key直达。当你把第一个管理page的page放进来的时候,这就是第一层b+树,当数据更多的时候,管理page的page也越来越多,那就需要第三层page来进一步管理,这就是两层b+树,以此类推,最终形成一个层层嵌套的hashmap结构,这就是b+树咯

  4. 那为什么page需要前后指针做成双链表呢?因为主键,比如就是id吧,查id大于10或者小于10的数据,那是不是就不需要一次次走树结构,只需要把id为10的数据的前指针或后指针吐出来就行,就快很多

  5. 那为什么mysql表推荐用自增主键呀?因为形成b+树更容易,我只需要按顺序往page后面贴数据就行,不需要做页内搬运计算

  6. 好了,单主键我们看完了,那联合索引呢?联合索引就是按照你指定的ABC三个字段,形成先排序A再排序B再排序C的有先后的主键,等于在b+树中用A做key找B,用B做key找C,所以如果查询的时候跳过了A,所有的索引就不生效了,因为你没有key,就没法用hashmap。有A没有B,那A会生效B不生效,原理一样

  7. 那么varchar字段为什么我加了索引,在做like ‘%bc%’的时候也会索引失效呀?和6一样,varchar按照字典序构建b+树,缺了最左的数据,没法查hashmap,就这么简单

  8. 那么回表又是什么呀?简单,我们在搞主键索引的时候,不是已经把真实数据存下来了嘛,那在构建其他索引的时候还需要存真实数据吗?不需要,浪费空间,所以我们查别的索引的时候,只需要在其他索引的b+树里查叶子结点的主键,那是不是就可以去主键索引的树查了呀?这就叫回表

  9. 那么覆盖索引为什么快呀?因为你要查询的字段都在b+树维护的索引树里面,跳过了8当中回表这一步,所以快

  10. 那么什么是聚簇索引什么是非聚簇索引呀?用来索引page的page就是聚簇索引,意思是把索引聚起来,反之就是非聚簇咯

  11. 为什么mysql不适合做全文索引而es可以呀?因为mysql用了b+树,对于字符串检索需要有从左到右的顺序,但es通过分词做了倒排索引,所以很容易做全文索引

其实也不难对吧,说穿了也就这么些

你们这些坏人,光收藏不点赞不关注是吧,好好好(~_~;)

——————分割线

看来大家对技术还挺有热情的,那我再分享点对springcloud的理解吧。

1. 微服务是种思想,你可以近似把微服务这个思想理解成一个接口,springcloud就是这个接口的implement

  1. 微服务是个什么思想呢?那就是一个服务只做一件事,功能隔离开,就像吃鸳鸯锅一样,一个格子只有一个味儿

  2. springcloud作为这种思想的实现,不是一种技术,而是一组技术的组合体,下面一个个说

  3. 服务拆开了,那微服务之间要互相发送信息吧,比如我是订单系统,你是发邮件给电子发票,那我们之间肯定要通信啊,我给你发个短信,你看到了就给xx用户把发票发过去。这时候就出现了MQ消息队列,MQ就是发短信,我只管发,你只管收,互相不管着

  4. 但是有时候不能发短信,得打电话,比如用户下订单了,我下单系统必须要风控系统立刻告诉我这个人有没有风险,不能等。那是不是就得打电话呀,这就是rpc或者http调用,A系统调用B系统的能力,并且实时得到结果。

6. http协议是不是有很多配置啊,这些配置都不是真实数据,那消息体是不是就会膨胀的很大呀,那就慢了对不对,所以后端微服务之间需要打电话的时候,就会选rpc,协议更精简,一次传输更多真实数据

  1. 问题又来了,我们服务越来越多,我怎么知道我该跟哪个服务打电话呀?这就是注册中心,服务上线的时候把自己需要的或者提供的能力告诉注册中心,由注册中心居中转接,就像电话交换机一样

  2. 运维的同学站起来了,说你们不能没完没了打电话啊,我cpu内存扛不住了都。不用急,我们给打电话加一个限制,每秒只允许打n个电话,这就是服务限流

  3. 运维的同学还是害怕,要是我们真有个服务电话被打停机了或者短信收不过来了(服务挂了),整个公司就完了啊,怎么办?别慌,兜底熔断策略做起来,如果接电话的服务扛不住了(达到某个阈值或者宕机了),不管如何直接给一个默认的结果,先继续跑,别让所有服务都寄。或者把短信和电话都先平移到别的系统,完全不做处理,只是先把数据接过来,这就是死信。

  4. 那你又要问了,如果我们一个服务并发量上去了,一个服务实例不够了呀,要水平扩容啊,人工做的话运维压力好大,怎么办?上容器嘛,一个镜像一个服务,k8s这个管家自动给你拉起,准备好运行环境,还给你做反向代理,负载均衡

  5. 哎,有同学说了,我项目正在运行,突然有个配置文件内容变了,我真不想改代码发版啊,怎么办?配置中心这不就来了吗,Apollo启动,跟你的服务开一个长连接,配置随改随更新,完全不用改代码发版,又是准点下班的一天

13. 网安的同学举手了,说我们这个后端服务的ip地址不能直接对外暴露啊,不然ddos了我死给你看。别急,统一网关这不就来了,由网关层统一接收所有请求,再由网关反向代理给真实服务嘛。这一步从设计模式上说叫前端设计模式,从网络路径上说叫外转内

  1. 用户拓展的同学也有话说,我们用户用我们的系统,每个功能都要登录一下,你们搞这个微服务干嘛啊,就不能一次登陆,每个系统都认这个登陆态吗?好说好说,单点登录给你弄上,用户的token我们进缓存,用缓存锁同步用户信息

  2. 运维的同学又有意见了,你们不能每次大难临头了才来找我们救火,能不能搞一套提前预警啊?也有办法,不慌,给你grafana和promethus,你想看图表算趋势看阈值,短信预警电话预警都能给你搞

  3. 这时候用户组的人也有问题了,你们这些微服务用容器做高并发的,万一多个用户,在生成用户id的时候重复了怎么整?雪花算法就来了,保证你一个人一个id不重样

我相信这些比较有意思的案例可以帮大家理解那些看起来很高大上的概念,希望喜欢咯

点个赞吧

——————分割线

我就知道还得有人问es哈哈,行吧,那挑点核心的说

  1. 从搜索和检索的区别开始

  2. 什么叫搜索?比如我在mysql查id=10,结果只有两种,要么存在,要么不存在,这是一个有和无,to be or not to be 的问题

  3. 什么叫检索?比如我在某度查“果子手机”,结果中有可能存在只包括“果”字的文档,有可能存在只包括“手机”的文档,也有可能存在同时包括“果”,“手机”的文档。也就是说检索是一个可能性问题,查询的结果有一定的概率是你要找的,有一定概率和你想要的压根不挨着

  4. 什么叫全文检索?对某个字段,我希望能够对所有已经保存的文档进行检索,这就叫全文检索

  5. 那全文检索怎么实现呢?我们看3中说的,不难总结出一个核心关键词,就是“分词”,我得在储存文档的时候就把字段做好分词,在用户发起查询的时候,我才能用同样的算法把用户想要查的内容也分词,最后做一个匹配对吧

  6. Es原生支持英文分词,但别担心,它允许咱装中文插件,ik什么的

  7. 现在我们有了上述的线索,就可以开始尝试理解倒排索引力

  8. 啥是倒排索引呢?倒排索引是一张结构化表,你可以简单地认为这张表只有俩字段,第一个字段叫“分词字段”,是6中分词后的每一个词语,第二个字段叫“文档编码字段”,是这个词语出现在哪几个真实的文档里。也就是说,有了倒排索引表,你既可以知道“手机”这个词语出现在哪几个文档里,也可以知道某个文档是否包含“手机”

  9. 倒排索引表是怎么生成的咧?es是这么玩的,一条数据进来,先把内容做分词,然后对分词去重,然后把当前这条数据的文档编号和分词插入到倒排索引表,然后再把这条真数据持久化。其中,“分词字段”是主键,因为去重后再存,天然保证这个字段是Unique

  10. 倒排索引表为啥适合全文索引呢?因为用户无需再扫描所有文档了,只需要拿“果子”,“手机”两个词语分别看看倒排索引这张表里,哪些文档有这些词儿,然后拿着文档的真实编号直接提取文档就行,就还是hashmap那个思想,拿key找value。所以大家看,hashmap还是有必要好好学的,哪儿都有它

  11. 但是还有个问题,这种非精确的检索吧,你不能啥结果都给我,或者说你得让我优先看到包含分词更多的文档吧?不然我作为用户还得老是去翻页找更相关的结果

  12. 有办法,给你计算相关度。啥是相关度呢?这是一种度量,用来评估Es给你返回的某一条数据,和用户查询的目标之间的相关性。

  13. 怎么计算相关度呢?比如你查“果子手机”,那么分词以后有三个词语“果”“子”“手机”,那么把三个词语共同的检查结果数量记为SUM,Xa记为a这篇文档在检查结果中出现了多少次,相关度=Xa/SUM。也就是说,一个文档包含的目标词语越多,相关度越好,展示越靠前

如何,你明白倒排索引了没?