欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入理解Spring源码:剖析循环依赖问题

最编程 2024-02-23 18:57:33
...

首先,我们在3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖 中手写了循环依赖的实现. 这个实现就是模拟的spring的循环依赖. 目的是为了更容易理解spring源码.

下面我们就进入正题, 看看spring的循环依赖源码.

 

一、getBean整体流程

 

目标很明确了, 就是要看看spring如何解决循环依赖的. 

代码入口是refresh()#finishBeanFactoryInitialization(beanFactory);

二、拆解研究流程中的每一步

调用方法beanFactory.preInstantiateSingletons();实例化剩余的单例bean. 为什么是剩余的?很显然我们在上面已经实例化一部分了.比如配置类, postProcessor等.

2.1 入口

1 @Override
 2     public void preInstantiateSingletons() throws BeansException {
 3         if (logger.isTraceEnabled()) {
 4             logger.trace("Pre-instantiating singletons in " + this);
 5         }
 6 
 7 
 8         // 获取容器中所有bean定义的名字
 9         List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
10 
11         // Trigger initialization of all non-lazy singleton beans...
12         /**
13          * 第一步: 循环bean定义的name
14          */
15         for (String beanName : beanNames) {
16             // 获取bean定义
17             RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
18             // 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean
19             if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
20                 // 这里判断是不是工厂bean, 这里和BeanFactory不是一个意思, 判断当前这个bean是否实现了beanFactory的接口
21                 if (isFactoryBean(beanName)) {
22                     Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
23                     if (bean instanceof FactoryBean) {
24                         final FactoryBean<?> factory = (FactoryBean<?>) bean;
25                         boolean isEagerInit;
26                         if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
27                             isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
28                                             ((SmartFactoryBean<?>) factory)::isEagerInit,
29                                     getAccessControlContext());
30                         }
31                         else {
32                             isEagerInit = (factory instanceof SmartFactoryBean &&
33                                     ((SmartFactoryBean<?>) factory).isEagerInit());
34                         }
35                         if (isEagerInit) {
36                             // 获取bean
37                             getBean(beanName);
38                         }
39                     }
40                 }
41                 else {
// 第二步: 调用bean定义
42                     getBean(beanName);
43                 }
44             }
45         }
46 
47         // Trigger post-initialization callback for all applicable beans...
48         
51         for (String beanName : beanNames) {
52             // 从缓存中得到实例instance
53             Object singletonInstance = getSingleton(beanName);
54             if (singletonInstance instanceof SmartInitializingSingleton) {
55                 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
56                 if (System.getSecurityManager() != null) {
57                     AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
58                         smartSingleton.afterSingletonsInstantiated();
59                         return null;
60                     }, getAccessControlContext());
61                 }
62                 else {
63                     smartSingleton.afterSingletonsInstantiated();
64                 }
65             }
66         }
67     }

 

首先, 循环bean定义, 这和我们模拟spring循环的第一步是一样的. 

第二步: 判断从BeanDefinitionMap中取出来的这个bean是否满足生产bean的条件

我们注意代码注释中, 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean

然后:调用getBean()

到目前为止,我们完成了上图源码图的第一部分:

 

 

 2.2 创建bean前的准备工作

接下来看看getBean().doGetBean()方法

 

1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  2             @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  3 
  4         // 第一步: 转换bean name. 在这里传入进来的name可能是别名, 也有可能是工厂bean的name, 所以在这里进行一个转换
  5         final String beanName = transformedBeanName(name);
  6         Object bean;
  7 
  8         // Eagerly check singleton cache for manually registered singletons.
  9         // 第二步: 尝试去缓存中获取对象, 如果没有获取到就创建bean
 10         Object sharedInstance = getSingleton(beanName);
 11         if (sharedInstance != null && args == null) {
 12             if (logger.isTraceEnabled()) {
 13                 //判断当前类是否是正在创建中
 14                 if (isSingletonCurrentlyInCreation(beanName)) {
 15                     logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 16                             "' that is not fully initialized yet - a consequence of a circular reference");
 17                 }
 18                 else {
 19                     logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 20                 }
 21             }
 22             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 23         }
 24 
 25         else {
 26             // Fail if we're already creating this bean instance:
 27             // We're assumably within a circular reference.
 28             /**
 29              * 判断当前的bean是不是多例, 如果是这抛出异常
 30              *
 31              * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
 32              * spring 只能解决单例对象的setter注入的循环依赖, 不能解决构造器注入
 33              *
 34              * 如果是多例的bean, 当前正在创建bean, 也会抛出异常---这也是循环依赖的问题
 35              */
 36             if (isPrototypeCurrentlyInCreation(beanName)) {
 37                 throw new BeanCurrentlyInCreationException(beanName);
 38             }
 39 
 40             /**
 41              * 下面这段代码是关于子父容器的, 只有spring mvc继承自spring, 才会有子父容器的问题.
 42              */
 43             // Check if bean definition exists in this factory.
 44             BeanFactory parentBeanFactory = getParentBeanFactory();
 45             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 46                 // Not found -> check parent.
 47                 String nameToLookup = originalBeanName(name);
 48                 if (parentBeanFactory instanceof AbstractBeanFactory) {
 49                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 50                             nameToLookup, requiredType, args, typeCheckOnly);
 51                 }
 52                 else if (args != null) {
 53                     // Delegation to parent with explicit args.
 54                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 55                 }
 56                 else if (requiredType != null) {
 57                     // No args -> delegate to standard getBean method.
 58                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 59                 }
 60                 else {
 61                     return (T) parentBeanFactory.getBean(nameToLookup);
 62                 }
 63             }
 64 
 65             /**
 66              * 方法参数typeCheckOnly是用来判断#getBean()方法时, 表示是否为仅仅进行类型检查,
 67              * 如果不仅仅做类型检查, 而是创建bean对象, 则需要调用#markBeanAsCreated(String name)
 68              *
 69              */
 70             if (!typeCheckOnly) {
 71                 markBeanAsCreated(beanName);
 72             }
 73 
 74             try {
 75                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 76                 checkMergedBeanDefinition(mbd, beanName, args);
 77 
 78                 // Guarantee initialization of beans that the current bean depends on.
 79                 /**
 80                  * 现在有两个bean1, bean2 , 加载的时候调用的是bean1, bean2. 但如果我们想要bean2优先加载, 就使用@DependOn注解
 81                  * 用来解析带有dependOn注解的类
 82                  */
 83                 String[] dependsOn = mbd.getDependsOn();
 84                 if (dependsOn != null) {
 85                     for (String dep : dependsOn) {
 86                         if (isDependent(beanName, dep)) {
 87                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 88                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 89                         }
 90                         registerDependentBean(dep, beanName);
 91                         try {
 92                             getBean(dep);
 93                         }
 94                         catch (NoSuchBeanDefinitionException ex) {
 95                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 96                                     "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
 97                         }
 98                     }
 99                 }
100 
101                 // Create bean instance.
102                 /**
103                  * 第三步: 创建单例bean实例
104                  */
105                 if (mbd.isSingleton()) { // 处理单例bean
106                     /**
107                      * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108                      * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> {
111                         try {
112                             return createBean(beanName, mbd, args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process, to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
121                     });
122                     // 得到bean实例对象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }
125 
126                 else if (mbd.isPrototype()) { // 处理多例bean
127                     // It's a prototype -> create a new instance.
128                     Object prototypeInstance = null;
129                     try {
130                         // 当前正在创建多例bean
131                         beforePrototypeCreation(beanName);
132                         // 执行创建bean
133                         prototypeInstance = createBean(beanName, mbd, args);
134                     }
135                     finally {
136                         afterPrototypeCreation(beanName);
137                     }
138                     // 获取bean实例对象
139                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140                 }
141 
142                 else { // 处理其他类型的bean
143                     String scopeName = mbd.getScope();
144                     final Scope scope = this.scopes.get(scopeName);
145                     if (scope == null) {
146                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147                     }
148                     try {
149                         Object scopedInstance = scope.get(beanName, () -> {
150                             beforePrototypeCreation(beanName);
151                             try {
152                                 return createBean(beanName, mbd, args);
153                             }
154                             finally {
155                                 afterPrototypeCreation(beanName);
156                             }
157                         });
158                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159                     }
160                     catch (IllegalStateException ex) {
161                         throw new BeanCreationException(beanName,
162                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164                                 ex);
165                     }
166                 }
167             }
168             catch (BeansException ex) {
169                 cleanupAfterBeanCreationFailure(beanName);
170                 throw ex;
171             }
172         } 

 

在这里, 首先从缓存中获取bean, 看缓存中是否已经存在了

 Object sharedInstance = getSingleton(beanName);

然后, 如果缓存中已经存在了,那么久直接取出来. 代码如下: 

if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                //判断当前bean是否是正在创建中(单例bean)
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

 

如果是空, 就说明是第一次创建, 执行else的部分

首先, 判断是否是正在创建的多例bean, 如果是正在创建的多例bean, 就抛出异常,

已经是正在创建了, 说明这至少是第二次了, 这里处理的是单例bean的循环依赖, 不处理多例bean的循环依赖, 所以抛出异常

对应的代码是这一句

// Fail if we're already creating this bean instance:
 27             // We're assumably within a circular reference.
 28             /**
 29              * 判断当前的bean是不是多例, 如果是这抛出异常
 30              *
 31              * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
 32              * spring 只能解决单例对象的setter注入的循环依赖, 不能解决构造器注入
 33              *
 34              * 如果是多例的bean, 当前正在创建bean, 也会抛出异常---这也是循环依赖的问题
 35              */
 36             if (isPrototypeCurrentlyInCreation(beanName)) {
 37                 throw new BeanCurrentlyInCreationException(beanName);
 38             }

那么, 接下来就是首次创建bean. 首次创建的bean有三种情况:

第一种, 这个bean是单例的.

第二种, 这个bean是多例的.

第三种. 其他类型

对应的代码就是这一块. 有行号, 可以和上面一一对应上

// Create bean instance.
102                 /**
103                  * 第三步: 创建单例bean实例
104                  */
105                 if (mbd.isSingleton()) { // 处理单例bean
106                     /**
107                      * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108                      * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> {
111                         try {
112                             return createBean(beanName, mbd, args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process, to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
121                     });
122                     // 得到bean实例对象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }
125 
126                 else if (mbd.isPrototype()) { // 处理多例bean
127                     // It's a prototype -> create a new instance.
128                     Object prototypeInstance = null;
129                     try {
130                         // 当前正在创建多例bean
131                         beforePrototypeCreation(beanName);
132                         // 执行创建bean
133                         prototypeInstance = createBean(beanName, mbd, args);
134                     }
135                     finally {
136                         afterPrototypeCreation(beanName);
137                     }
138                     // 获取bean实例对象
139                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140                 }
141 
142                 else { // 处理其他类型的bean
143                     String scopeName = mbd.getScope();
144                     final Scope scope = this.scopes.get(scopeName);
145                     if (scope == null) {
146                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147                     }
148                     try {
149                         Object scopedInstance = scope.get(beanName, () -> {
150                             beforePrototypeCreation(beanName);
151                             try {
152                                 return createBean(beanName, mbd, args);
153                             }
154                             finally {
155                                 afterPrototypeCreation(beanName);
156                             }
157                         });
158                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159                     }
160                     catch (IllegalStateException ex) {
161                         throw new BeanCreationException(beanName,
162                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164                                 ex);
165                     }
166                 }

 

我们的重点研究对象是单例bean. 所以,重点看单例bean的实现

105                 if (mbd.isSingleton()) { // 处理单例bean
106                     /**
107                      * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108                      * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109                      */
110                     sharedInstance = getSingleton(beanName, () -> {
111                         try {
112                             return createBean(beanName, mbd, args);
113                         }
114                         catch (BeansException ex) {
115                             // Explicitly remove instance from singleton cache: It might have been put there
116                             // eagerly by the creation process, to allow for circular reference resolution.
117                             // Also remove any beans that received a temporary reference to the bean.
118                             destroySingleton(beanName);
119                             throw ex;
120                         }
121                     });
122                     // 得到bean实例对象
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }

 

这里的重点是调用了getSingleton(beanName, FactoryObject); FactoryObject是一个接口. 定义了一个钩子方法getObject(). 

这个接口在这里这是进行了定义, 并不会执行. 什么时候执行呢? 后面调用的时候执行. 

下面来看看getSingleton()方法, 钩子方法也是在这里被调用的.

 1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 2         Assert.notNull(beanName, "Bean name must not be null");
 3         synchronized (this.singletonObjects) {
 4             // 第一步: 从一级缓存中获取单例对象
 5             Object singletonObject = this.singletonObjects.get(beanName);
 6             if (singletonObject == null) {
 7                 if (this.singletonsCurrentlyInDestruction) {
 8                     throw new BeanCreationNotAllowedException(beanName,
 9                             "Singleton bean creation not allowed while singletons of this factory are in destruction " +
10                             "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
11                 }
12                 
						

上一篇: 如何在Spring框架中:轻松获取、保存及编译源代码 - 遇到的编译问题与解决方案

下一篇: 如何在IDEA中为Spring源码开发创建调试环境的学习指南

推荐阅读