因为我不知道 Spring 的 depends-on 用法, 半天没看懂源码

声明

本文的主要目的不是来讲解 Spring 的 depends-on 的相关概念和如何使用的, 更不是来分析源码的,

而是想借助本文的案例说明两点关于阅读源码的体会:

  1. 要想读通框架源码, 首先你得先玩儿通.
  2. 阅读源码过程中或者看了他人对源码的分析见解后, 自己也要去 debug 验证一下.

正文

自己用 Spring 做业务开发两年了, 但是从来没有接触或用到过它的 depends-on 特性.因此当在源码中看到这个词汇时, 很容易把它跟我们常用的 依赖注入 扯在一起, 最终导致自己对框架源码的理解产生了疑虑.

先回顾一下如何配置依赖注入

在配置 Spring 的 Bean 以及 Bean 之间的依赖关系时, 我们经常使用 xml 或者 注解 的方式. 下面我们用 xml 的方式回顾一下如何配置 Spring 的依赖注入.

假设我们有一个 User 对象, 这个 User 对象依赖一个 Car 对象. 于是我们有了如下的配置:

<!--Car-->
<bean class="com.demo.Car" id="car">
</bean>

<!-- User -->
<bean class="com.demo.User" id="user">
    <property name="car" ref="car"/>
</bean>

再引入循环依赖的概念

还拿上面 User 和 Car 的来举例, 循环依赖 就是 User 对象依赖 Car 对象, Car 对象 又依赖了 User 对象, 从而造成了如下关系图:

因为我不知道 Spring 的 depends-on 用法, 半天没看懂源码
同时, 我们要了解到的是 Spring 对于单例 Bean,并且通过 setter 方法注入依赖的情况, 是可以解决掉 Spring 循环依赖的, 也就是说下面的配置关系是不会出错的.

<!--Car-->
<bean class="com.demo.Car" id="car">
  <property name="user" ref="user"/>
</bean>

<!-- User -->
<bean class="com.demo.User" id="user">
    <property name="car" ref="car"/>
</bean>

最后窥探下获取 Bean 的“源码”

完整的源码可以参考 org.springframework.beans.factory.support.AbstractBeanFactory#getBean

但是方便说明问题, 我们需要对 getBean 方法做如下简化, 同时基于我们上面对 Spring 依赖注入的了解, 自然而然就轻易给出了如下的注释:

public Object getBean(String beanName) {
    // 1.先拿到 Bean 的定义
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    
    // 2.如果当前 bean 有依赖其他 Bean, 就先把依赖的 Bean 实例化
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
	      for (String dep : dependsOn) {
				getBean(dep);		
		  }
    }
  
    // TODO 
}

通过分析上面的逻辑, 我们发现当遇见 循环依赖 时, 一旦执行到第二个步骤就会出现无限递归的情况.

这个时候头上就会出现一堆问号, dependsOn 就是依赖的意思啊, 难道我的理解有问题? 更难受的是当时因为一些条件限制, 我没办法去做 debug, 并且之前在看别人对 Spring 源码分析的相关文章时, 也几乎没人提到这段源码, 最后通过源码搜索, 才查到 Spring 中存在 dependsOn 的相关概念和用法. 具体的 Xml 的配置如下:

<bean id="car" class="com.demo.Car">  
  
<bean id="user" class="User"  depends-on="car"/>  

同时, 这里对 depends-on 的用法给出一个简短的解释, 需要详细了解的, 请自行检索.

depends-on 适用于表面上看起来两个 bean 之间没有使用属性之类的强连接的 bean,但是两个 bean 又确实存在前后依赖关系的情况,使用了depends-on的时候,依赖他人的 bean 是先于被依赖 bean 销毁的

总而言之, 这个“依赖” 跟我们常说(用)的那个依赖注入是两回事.

总结

因为不知道 Spring 中 “depends-on” 用法的存在, 加上阅读源码时没能够第一时间去 debug, 导致在阅读 get Bean 源码过程中困惑了许久. 当然文中只说了 “depends-on” 这一个例子, 但是我们也不可能把 Spring 的所有用法都了解一遍再去看源码, 因此在借助一些文章阅读源码时, 既要自己做 debug 验证, 也得要求自己尽量对 Spring 的一些“不常见” 的用法和概念掌握后, 再去深度了解源码.

简单总结, 问题根源在于我们 “眼高手低” 的坏习惯和 ”用什么学什么的“ 的工作方法.

下面先简单列一些对于平常只用 Spring 写业务的人不大可能用到的一些类或概念:

  • Spring 的父子容器的概念

  • Spring 循环依赖的概念

  • Spring init-method 初始化方法

  • Aware 接口的用法

  • FactoryBean 接口的用法

  • BeanPostProcessor 接口的用法

  • BeanFactoryPostProcessor 接口的用法

  • InitializingBean 接口的用法

  • 等等

同时, 下一篇文章将会对上述提到的概念和类做详细讲解, 写给 ”我们这一类人“.

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值