先提出些问题?
1、Spring 的Bean是怎么产生的?
2、它的生命周期是如何的?
3、Spring的Bean是如何解决循环依赖的?

用xml配置的

  1. <!--循环依赖问题-->
  2. <bean id="instanceA" class="com.lagou.edu.InstanceA">
  3. <property name="InstanceB" ref="instanceB"/>
  4. </bean>
  5. <bean id="instanceB" class="com.lagou.edu.InstanceB">
  6. <property name="InstanceA" ref="instanceA"/>
  7. </bean>

根据问题1,Spring 的Bean是怎么产生的?

1

image.png

2

image.png

3、接下来就是要看产生bean的逻辑代码

image.png

4

image.png

5

image.png

6

image.png

7

image.png

8

image.png

9

image.png

10

image.png

11

image.png

12

image.png

13

image.png

14

image.png

15

image.png

16

image.png

17

——————————————————————
》》》》》》》》》》》》》》》》》》》》》》》》》
其实可以看看new NamedBeanHolder()方法里面,发现里面传入xml的id,也就是beanName,
还有就是bean实例。那么现在就需要去找这两个东西才能进行赋值哦。
image.png

18

image.png
———————————————————————————-
》》》》》》》》》》》》》》》》》》》》》》》》》

19

image.png

20

image.png

21

其实第一次是先从缓存取getSingleton(beanName),如果取不到才去创建的。
image.png

22

image.png

23

image.png

24

这里是先从一级缓存中取,如果一级缓存没有就从二级缓存获取,如果二级也空,
但是缓存工厂(三级缓存)不为空,就从缓存工厂(三级缓存)中取,并将其从三级缓存删除,取到级二缓存中
image.png

25

一路走完,到单例缓存池获取的时候,进来就能拿到了(里面有三层判断),为什么能拿到呢,谁放的呢?
image.png

能从单例缓存池中拿,那么就有放,取存守恒原则,能取就有放,那么肯定有地方put进去
全局搜索singletonObjects.put,并在此处打断点,通过debug模式看他什么时候放进去的。
再通过左下角的调用栈,反推它是从哪里调进来的。具体步骤如下:
其实发现,put进去时候,也从二三级缓存删除了。

26

image.png

点进去addSingleton,并添加过滤条件。重启debug进来。

27

image.png

28

看看怎么放到一级缓存
image.png

》》》》》》》》》》》》》》》》》》》》

29查看具体的调用栈

可以根据调用栈的信息,点进去看。
image.png

》》》》》》》》》》》》》》》》》》》》

30

image.png

31

这里是通过javasa进行的
image.png

32

image.png

====================》》》》》》》》》》》》》》》》》

33

如果是通过xml配置信息进行处理
image.png

34

image.png

35

image.png
====================》》》》》》》》》》》》》》》》》

36

到了refresh()方法里面都是要经过这个步骤的
image.png

37

结合刚刚通过调用栈进行反推,晓得
finishBeanFactoryInitialization 调用后是 ,preInstantiateSingletons又有调用
这里面是真正实例化Bean的逻辑
image.png

38

配合调用栈进行反推,晓得
preInstantiateSingletons调用后是 ,又有调用getBean()的
但是preInstantiateSingletons方法里面有调用getBean()的有好几个呢(可以先走流程,然后通过调用栈看是调用哪个具体的getBean())
image.png

39

image.png

40

image.png

41

image.png

42

当流程走完,发现sharedInstance = getSingleton(beanName, () -> {这行代码有返回实例
image.png

43

image.png

44

而且这些也需要有返回值哦,进入同样得先走完流程,看有返回值的那行代码
image.png

45

image.png

46

通过回退代码查看
image.png

47

image.png

48

image.png

在这里就得到了问题一的答案了,
Spring 的Bean是在doCreateBean方法中调用了无参构造初始化了Bean对象
这个方法里面也是解决依赖的关键。

49

image.png

50如何通过构造方法创建实例Bean

创建实例BeanA剖析开始

===================》start
image.png

51

image.png

52

第一次是先获取instantiationStrategy,然后调用instantiate方法。
image.png

53

image.png

54

image.png
进入是先有isKotlinReflectPresent返回,再进入。就会去调用无参构造了

55

image.png

56

image.png

57

image.png

创建实例BeanA剖析结束

====================》》》》》》》》》》》end

58拿到实例Bean后都干啥呢?

image.png

59

image.png

60

image.png

61

image.png

62

其实也可以结合调用栈晓得是调这个方法
image.png

63

image.png

64

image.png

65

image.png

66

image.png

67

image.png

68

image.png

69

image.png

70

image.png

71

image.png

72

其实这个方法一开始是从单例缓存池拿不到的,它是一个未成熟的Bean,
把无参构造创建出来实例Bean放入三级缓存。(A之前已经放过咯,现在放B咯)
image.png

73通过构造方法创建实例BeanB并填充属性开始

image.png

74

image.png

75

image.png

76

image.png

77

image.png

78

image.png

79

image.png

80

image.png

81

image.png

82

image.png


83得到实例BeanA就一直返回。

image.png

84

image.png
一路走完流程

85

image.png

86

image.png

然后又一路返回

87

image.png

88

image.png

89

image.png

90

image.png

91

image.png

92

image.png

93

image.png

94

image.png

95

image.png

96

image.png

97

image.png

98

image.png

99

image.png

100

image.png

101

image.png

==============================
注意:前置、后置方法都是进行遍历的。
image.png


org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
org.springframework.beans.factory.support.AbstractBeanFactory#getBean
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java:238
org.springframework.beans.factory.support.AbstractBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
org.springframework.beans.factory.support.AbstractBeanFactory#createBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
……..

image.png

image.png

image.png

image.png

这是因为创建A的过程中,发现它依赖于B,所以它要去创建B,重复刚刚A走过的步骤

但是有个疑问?它点进去的方法怎么找不到呢?
image.png

注意:借鉴物理的质量守恒原则,可以有一个取存守恒原则,有取就有存,有get就有put。
那么在哪里给它put进去了呢?哪里创建的呢?(逆向思维,反向工程)