IoC 之加载 Bean:总结

Posted zcg1051980588

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IoC 之加载 Bean:总结相关的知识,希望对你有一定的参考价值。

上文中我们将bean已经加载到了IOC容器中,接下来我们将把IOC加载Bean出来进行代码解析 备注:(有些解释是参考别个博客的相关解释 )一起探讨请加我QQ:1051980588

bean 的初始化节点,由第一次(显式或者隐式)调用 #getBean(...) 方法来开启,所以我们从这个方法开始。代码如下:

 

  1 // AbstractBeanFactory.java
  2 
  3 public Object getBean(String name) throws BeansException {
  4     return doGetBean(name, null, null, false);
  5 }
  6 
  7 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
  8         @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
  9     // <1> 返回 bean 名称,剥离工厂引用前缀。
 10     // 如果 name 是 alias ,则获取对应映射的 beanName 。
 11     final String beanName = transformedBeanName(name);
 12     Object bean;
 13 
 14     // 从缓存中或者实例工厂中获取 Bean 对象
 15     // Eagerly check singleton cache for manually registered singletons.
 16     Object sharedInstance = getSingleton(beanName);
 17     if (sharedInstance != null && args == null) {
 18         if (logger.isTraceEnabled()) {
 19             if (isSingletonCurrentlyInCreation(beanName)) {
 20                 logger.trace("Returning eagerly cached instance of singleton bean ‘" + beanName +
 21                         "‘ that is not fully initialized yet - a consequence of a circular reference");
 22             } else {
 23                 logger.trace("Returning cached instance of singleton bean ‘" + beanName + "‘");
 24             }
 25         }
 26         // <2> 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
 27         bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 28     } else {
 29         // Fail if we‘re already creating this bean instance:
 30         // We‘re assumably within a circular reference.
 31         // <3> 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
 32         if (isPrototypeCurrentlyInCreation(beanName)) {
 33             throw new BeanCurrentlyInCreationException(beanName);
 34         }
 35 
 36         // <4> 如果容器中没有找到,则从父类容器中加载
 37         // Check if bean definition exists in this factory.
 38         BeanFactory parentBeanFactory = getParentBeanFactory();
 39         if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 40             // Not found -> check parent.
 41             String nameToLookup = originalBeanName(name);
 42             if (parentBeanFactory instanceof AbstractBeanFactory) {
 43                 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 44                         nameToLookup, requiredType, args, typeCheckOnly);
 45             } else if (args != null) {
 46                 // Delegation to parent with explicit args.
 47                 return (T) parentBeanFactory.getBean(nameToLookup, args);
 48             } else if (requiredType != null) {
 49                 // No args -> delegate to standard getBean method.
 50                 return parentBeanFactory.getBean(nameToLookup, requiredType);
 51             } else {
 52                 return (T) parentBeanFactory.getBean(nameToLookup);
 53             }
 54         }
 55 
 56         // <5> 如果不是仅仅做类型检查则是创建bean,这里需要记录 
 57         if (!typeCheckOnly) {
 58             markBeanAsCreated(beanName);
 59         }
 60 
 61         try {
 62             // <6> 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
 63             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 64             // 检查给定的合并的 BeanDefinition
 65             checkMergedBeanDefinition(mbd, beanName, args);
 66 
 67             // Guarantee initialization of beans that the current bean depends on.
 68             // <7> 处理所依赖的 bean
 69             String[] dependsOn = mbd.getDependsOn();
 70             if (dependsOn != null) {
 71                 for (String dep : dependsOn) {
 72                     // 若给定的依赖 bean 已经注册为依赖给定的 bean
 73                     // 循环依赖的情况
 74                     if (isDependent(beanName, dep)) {
 75                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 76                                 "Circular depends-on relationship between ‘" + beanName + "‘ and ‘" + dep + "‘");
 77                     }
 78                     // 缓存依赖调用 TODO 芋艿
 79                     registerDependentBean(dep, beanName);
 80                     try {
 81                         getBean(dep);
 82                     } catch (NoSuchBeanDefinitionException ex) {
 83                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 84                                 "‘" + beanName + "‘ depends on missing bean ‘" + dep + "‘", ex);
 85                     }
 86                 }
 87             }
 88 
 89             // <8> bean 实例化
 90             // Create bean instance.
 91             if (mbd.isSingleton()) { // 单例模式
 92                 sharedInstance = getSingleton(beanName, () -> {
 93                     try {
 94                         return createBean(beanName, mbd, args);
 95                     }
 96                     catch (BeansException ex) {
 97                         // Explicitly remove instance from singleton cache: It might have been put there
 98                         // eagerly by the creation process, to allow for circular reference resolution.
 99                         // Also remove any beans that received a temporary reference to the bean.
100                         // 显式从单例缓存中删除 Bean 实例
101                         // 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。 TODO 芋艿
102                         destroySingleton(beanName);
103                         throw ex;
104                     }
105                 });
106                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
107             } else if (mbd.isPrototype()) { // 原型模式
108                 // It‘s a prototype -> create a new instance.
109                 Object prototypeInstance;
110                 try {
111                     beforePrototypeCreation(beanName);
112                     prototypeInstance = createBean(beanName, mbd, args);
113                 } finally {
114                     afterPrototypeCreation(beanName);
115                 }
116                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
117             } else {
118                 // 从指定的 scope 下创建 bean
119                 String scopeName = mbd.getScope();
120                 final Scope scope = this.scopes.get(scopeName);
121                 if (scope == null) {
122                     throw new IllegalStateException("No Scope registered for scope name ‘" + scopeName + "‘");
123                 }try {
124                     Object scopedInstance = scope.get(beanName, () -> {
125                         beforePrototypeCreation(beanName);
126                         try {
127                             return createBean(beanName, mbd, args);
128                         } finally {
129                             afterPrototypeCreation(beanName);
130                         }
131                     });
132                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
133                 } catch (IllegalStateException ex) {
134                     throw new BeanCreationException(beanName,
135                             "Scope ‘" + scopeName + "‘ is not active for the current thread; consider " +
136                             "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
137                             ex);
138                 }
139             }
140         } catch (BeansException ex) {
141             cleanupAfterBeanCreationFailure(beanName);
142             throw ex;
143         }
144     }
145 
146     // <9> 检查需要的类型是否符合 bean 的实际类型
147     // Check if required type matches the type of the actual bean instance.
148     if (requiredType != null && !requiredType.isInstance(bean)) {
149         try {
150             T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
151             if (convertedBean == null) {
152                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
153             }
154             return convertedBean;
155         } catch (TypeMismatchException ex) {
156             if (logger.isTraceEnabled()) {
157                 logger.trace("Failed to convert bean ‘" + name + "‘ to required type ‘" +
158                         ClassUtils.getQualifiedName(requiredType) + "‘", ex);
159             }
160             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
161         }
162     }
163     return (T) bean;
164 }

内部调用 #doGetBean(...) 方法。#doGetBean(...) 方法的代码量比较多,从这里就可以看出 bean 的加载过程是一个非常复杂的过程,会涉及到各种各样的情况处理。

#doGetBean(...) 方法,可以分为以下几个过程:

  1. 转换 beanName 。因为我们调用 #getBean(...) 方法传入的 name 并不一定就是 beanName,可以传入 aliasName,FactoryBean,所以这里需要进行简单的转换过程。
  2. 尝试从缓存中加载单例 bean 。
  3. bean 的实例化。
  4. 原型模式的依赖检查。因为 Spring 只会解决单例模式的循环依赖,对于原型模式的循环依赖都是直接抛出 BeanCurrentlyInCreationException 异常。
  5. 尝试从 parentBeanFactory 获取 bean 实例。如果 parentBeanFactory != null && !containsBeanDefinition(beanName) 则尝试从 parentBeanFactory 中获取 bean 实例对象,因为 !containsBeanDefinition(beanName) 就意味着定义的 xml 文件中没有 beanName 相应的配置,这个时候就只能从 parentBeanFactory 中获取。
  6. 获取 RootBeanDefinition,并对其进行合并检查。从缓存中获取已经解析的 RootBeanDefinition 。同时,如果父类不为 null的话,则会合并父类的属性。
  7. 依赖检查。某个 bean 依赖其他 bean ,则需要先加载依赖的 bean。
  8. 对不同的 scope 进行处理。
  9. 类型转换处理。如果传递的 requiredType 不为 null,则需要检测所得到 bean 的类型是否与该 requiredType 一致。如果不一致则尝试转换,当然也要能够转换成功,否则抛出 BeanNotOfRequiredTypeException 异常。

下面就以下几个方面进行阐述,说明 Spring bean 的加载过程。

  1. 从缓存中获取 bean
  2. 创建 bean 实例对象
  3. 从 bean 实例中获取对象

1. 从缓存中获取 bean

Spring 中根据 scope 可以将 bean 分为以下几类:singleton、prototype 和 其他,这样分的原因在于 Spring 在对不同 scope 处理的时候是这么处理的:

  • singleton :在 Spring 的 IoC 容器中只存在一个对象实例,所有该对象的引用都共享这个实例。Spring 容器只会创建该 bean 定义的唯一实例,这个实例会被保存到缓存中,并且对该bean的所有后续请求和引用都将返回该缓存中的对象实例。
  • prototype :每次对该bean的请求都会创建一个新的实例
  • 其他 :
    • request:每次 http 请求将会有各自的 bean 实例。
    • session:在一个 http session 中,一个 bean 定义对应一个 bean 实例。
    • global session:在一个全局的 http session 中,一个 bean 定义对应一个 bean 实例。

所以,从缓存中获取的 bean 一定是 singleton bean,这也是 Spring 为何只解决 singleton bean 的循环依赖。调用 #getSingleton(String beanName) 方法,从缓存中获取 singleton bean。代码如下:

 

 1 // DefaultSingletonBeanRegistry.java
 2 
 3 public Object getSingleton(String beanName) {
 4     return getSingleton(beanName, true);
 5 }
 6 
 7 @Nullable
 8 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
 9     // 从单例缓冲中加载 bean
10     Object singletonObject = this.singletonObjects.get(beanName);
11     // 缓存中的 bean 为空,且当前 bean 正在创建
12     if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
13         // 加锁
14         synchronized (this.singletonObjects) {
15             // 从 earlySingletonObjects 获取
16             singletonObject = this.earlySingletonObjects.get(beanName);
17             // earlySingletonObjects 中没有,且允许提前创建
18             if (singletonObject == null && allowEarlyReference) {
19                 // 从 singletonFactories 中获取对应的 ObjectFactory
20                 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
21                 if (singletonFactory != null) {
22                     // 获得 bean
23                     singletonObject = singletonFactory.getObject();
24                     // 添加 bean 到 earlySingletonObjects 中
25                     this.earlySingletonObjects.put(beanName, singletonObject);
26                     // 从 singletonFactories 中移除对应的 ObjectFactory
27                     this.singletonFactories.remove(beanName);
28                 }
29             }
30         }
31     }
32     return singletonObject;
33 }

 

该方法就是从 singletonObjectsearlySingletonObjects、 singletonFactories 三个缓存中获取,这里也是 Spring 解决 bean 循环依赖的关键之处。

2. 创建 bean 实例对象

如果缓存中没有,也没有 parentBeanFactory ,则会调用 #createBean(String beanName, RootBeanDefinition mbd, Object[] args) 方法,创建 bean 实例。该方法主要是在处理不同 scope 的 bean 的时候进行调用。代码如下:

1 // AbstractBeanFactory.java
2 
3 protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
4             throws BeanCreationException;

 

  • 该方法是定义在 AbstractBeanFactory 中的抽象方法,其含义是根据给定的 BeanDefinition 和 args 实例化一个 bean 对象。如果该 BeanDefinition 存在父类,则该 BeanDefinition 已经合并了父类的属性。所有 Bean 实例的创建都会委托给该方法实现。
  • 方法接受三个参数:
    • beanName :bean 的名字。
    • mbd :已经合并了父类属性的(如果有的话)BeanDefinition 。
    • args :用于构造函数或者工厂方法创建 bean 实例对象的参数 。

该抽象方法的默认实现是在类 AbstractAutowireCapableBeanFactory 中实现,该方法其实只是做一些检查和验证工作,真正的初始化工作是由 #doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法来实现。代码如下

  1 // AbstractAutowireCapableBeanFactory.java        
  2 
  3 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  4         throws BeanCreationException {
  5 
  6     // Instantiate the bean.
  7     // BeanWrapper 是对 Bean 的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装 bean 的属性描述器
  8     BeanWrapper instanceWrapper = null;
  9     // <1> 单例模型,则从未完成的 FactoryBean 缓存中删除
 10     if (mbd.isSingleton()) {
 11         instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 12     }
 13     // <2> 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
 14     if (instanceWrapper == null) {
 15         instanceWrapper = createBeanInstance(beanName, mbd, args);
 16     }
 17     // 包装的实例对象
 18     final Object bean = instanceWrapper.getWrappedInstance();
 19     // 包装的实例对象的类型
 20     Class<?> beanType = instanceWrapper.getWrappedClass();
 21     if (beanType != NullBean.class) {
 22         mbd.resolvedTargetType = beanType;
 23     }
 24 
 25     // Allow post-processors to modify the merged bean definition.
 26     // <3> 判断是否有后置处理
 27     // 如果有后置处理,则允许后置处理修改 BeanDefinition
 28     synchronized (mbd.postProcessingLock) {
 29         if (!mbd.postProcessed) {
 30             try {
 31                 // 后置处理修改 BeanDefinition
 32                 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 33             } catch (Throwable ex) {
 34                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 35                         "Post-processing of merged bean definition failed", ex);
 36             }
 37             mbd.postProcessed = true;
 38         }
 39     }
 40 
 41     // Eagerly cache singletons to be able to resolve circular references
 42     // even when triggered by lifecycle interfaces like BeanFactoryAware.
 43     // <4> 解决单例模式的循环依赖
 44     boolean earlySingletonExposure = (mbd.isSingleton() // 单例模式
 45             && this.allowCircularReferences // 运行循环依赖
 46             && isSingletonCurrentlyInCreation(beanName)); // 当前单例 bean 是否正在被创建
 47     if (earlySingletonExposure) {
 48         if (logger.isTraceEnabled()) {
 49             logger.trace("Eagerly caching bean ‘" + beanName +
 50                     "‘ to allow for resolving potential circular references");
 51         }
 52         // 提前将创建的 bean 实例加入到 singletonFactories 中
 53         // 这里是为了后期避免循环依赖
 54         addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 55     }
 56 
 57     // Initialize the bean instance.
 58     // 开始初始化 bean 实例对象
 59     Object exposedObject = bean;
 60     try {
 61         // <5> 对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
 62         // 则会递归初始依赖 bean
 63         populateBean(beanName, mbd, instanceWrapper);
 64         // <6> 调用初始化方法
 65         exposedObject = initializeBean(beanName, exposedObject, mbd);
 66     } catch (Throwable ex) {
 67         if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 68             throw (BeanCreationException) ex;
 69         } else {
 70             throw new BeanCreationException(
 71                     mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 72         }
 73     }
 74 
 75     // <7> 循环依赖处理
 76     if (earlySingletonExposure) {
 77         // 获取 earlySingletonReference
 78         Object earlySingletonReference = getSingleton(beanName, false);
 79         // 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
 80         if (earlySingletonReference != null) {
 81             // 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
 82             if (exposedObject == bean) {
 83                 exposedObject = earlySingletonReference;
 84             // 处理依赖
 85             } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 86                 String[] dependentBeans = getDependentBeans(beanName);
 87                 Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
 88                 for (String dependentBean : dependentBeans) {
 89                     if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
 90                         actualDependentBeans.add(dependentBean);
 91                     }
 92                 }
 93                 if (!actualDependentBeans.isEmpty()) {
 94                     throw new BeanCurrentlyInCreationException(beanName,
 95                             "Bean with name ‘" + beanName + "‘ has been injected into other beans [" +
 96                             StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 97                             "] in its raw version as part of a circular reference, but has eventually been " +
 98                             "wrapped. This means that said other beans do not use the final version of the " +
 99                             "bean. This is often the result of over-eager type matching - consider using " +
100                             "‘getBeanNamesOfType‘ with the ‘allowEagerInit‘ flag turned off, for example.");
101                 }
102             }
103         }
104     }
105 
106     // Register bean as disposable.
107     // <8> 注册 bean
108     try {
109         registerDisposableBeanIfNecessary(beanName, bean, mbd);
110     } catch (BeanDefinitionValidationException ex) {
111         throw new BeanCreationException(
112                 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
113     }
114 
115     return exposedObject;
116 }


#doCreateBean(...) 方法,是创建 bean 实例的核心方法,它的整体思路是:

  • <1> 处,如果是单例模式,则清除 factoryBeanInstanceCache 缓存,同时返回 BeanWrapper 实例对象,当然如果存在。
  • <2> 处,如果缓存中没有 BeanWrapper 或者不是单例模式,则调用 #createBeanInstance(...) 方法,实例化 bean,主要是将 BeanDefinition 转换为 BeanWrapper 。
  • <3> 处,MergedBeanDefinitionPostProcessor 的应用。
  • <4> 处,单例模式的循环依赖处理。
  • <5> 处,调用 #populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) 方法,进行属性填充。将所有属性填充至 bean 的实例中。
  • <6> 处,调用 #initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法,初始化 bean 。
  • <7> 处,依赖检查。
  • <8> 处,注册 DisposableBean 。

2.1 实例化 bean

如果缓存中没有 BeanWrapper 实例对象或者该 bean 不是 singleton,则调用 #createBeanInstance(...) 方法。创建 bean 实例。该方法主要是根据参数 BeanDefinition、args[] 来调用构造函数实例化 bean 对象。过程较为复杂,代码如下:

 1 // AbstractAutowireCapableBeanFactory.java
 2 
 3 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
 4     // Make sure bean class is actually resolved at this point.
 5     // 解析 bean ,将 bean 类名解析为 class 引用。
 6     Class<?> beanClass = resolveBeanClass(mbd, beanName);
 7 
 8     if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) { // 校验
 9         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
10                 "Bean class isn‘t public, and non-public access not allowed: " + beanClass.getName());
11     }
12 
13     // <1> 如果存在 Supplier 回调,则使用给定的回调方法初始化策略
14     Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
15     if (instanceSupplier != null) {
16         return obtainFromSupplier(instanceSupplier, beanName);
17     }
18 
19     // <2> 使用 FactoryBean 的 factory-method 来创建,支持静态工厂和实例工厂
20     if (mbd.getFactoryMethodName() != null)  {
21         return instantiateUsingFactoryMethod(beanName, mbd, args);
22     }
23 
24     // <3> Shortcut when re-creating the same bean...
25     boolean resolved = false;
26     boolean autowireNecessary = false;
27     if (args == null) {
28         // constructorArgumentLock 构造函数的常用锁
29         synchronized (mbd.constructorArgumentLock) {
30             // 如果已缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
31             // 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所有采用缓存机制
32             if (mbd.resolvedConstructorOrFactoryMethod != null) {
33                 resolved = true;
34                 autowireNecessary = mbd.constructorArgumentsResolved;
35             }
36         }
37     }
38     // 已经解析好了,直接注入即可
39     if (resolved) {
40         // <3.1> autowire 自动注入,调用构造函数自动注入
41         if (autowireNecessary) {
42             return autowireConstructor(beanName, mbd, null, null);
43         } else {
44             // <3.2> 使用默认构造函数构造
45             return instantiateBean(beanName, mbd);
46         }
47     }
48 
49     // Candidate constructors for autowiring?
50     // <4> 确定解析的构造函数
51     // 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
52     Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
53     // <4.1> 有参数情况时,创建 Bean 。先利用参数个数,类型等,确定最精确匹配的构造方法。
54     if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
55             mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
56         return autowireConstructor(beanName, mbd, ctors, args);
57     }
58 
59     // Preferred constructors for default construction?
60     // <4.1> 选择构造方法,创建 Bean 。
61     ctors = mbd.getPreferredConstructors();
62     if (ctors != null) {
63         return autowireConstructor(beanName, mbd, ctors, null); // args = null
64     }
65 
66     // No special handling: simply use no-arg constructor.
67     // <4.2> 有参数时,又没获取到构造方法,则只能调用无参构造方法来创建实例了(兜底方法)
68     return instantiateBean(beanName, mbd);
69 }

实例化 Bean 对象,是一个复杂的过程,其主要的逻辑为:

  • <1> 处,如果存在 Supplier 回调,则调用 #obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) 方法,进行初始化。
  • <2> 处,如果存在工厂方法,则使用工厂方法进行初始化。
  • <3> 处,首先判断缓存,如果缓存中存在,即已经解析过了,则直接使用已经解析了的。根据 constructorArgumentsResolved 参数来判断:
    • <3.1> 处,是使用构造函数自动注入,即调用 #autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) 方法。
    • <3.2> 处,还是默认构造函数,即调用 #instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。
  • <4> 处,如果缓存中没有,则需要先确定到底使用哪个构造函数来完成解析工作,因为一个类有多个构造函数,每个构造函数都有不同的构造参数,所以需要根据参数来锁定构造函数并完成初始化。
    • <4.1> 处,如果存在参数,则使用相应的带有参数的构造函数,即调用 #autowireConstructor(String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) 方法。
    • <4.2> 处,否则,使用默认构造函数,即调用 #instantiateBean(final String beanName, final RootBeanDefinition mbd) 方法。

其实核心思想还是在于根据不同的情况执行不同的实例化策略,主要是包括如下四种策略:

  1. Supplier 回调
  2. #instantiateUsingFactoryMethod(...) 方法,工厂方法初始化
  3. #autowireConstructor(...) 方法,构造函数自动注入初始化
  4. #instantiateBean(...) 方法,默认构造函数注入

其实无论哪种策略,他们的实现逻辑都差不多:确定构造函数和构造方法,然后实例化。只不过相对于 Supplier 回调和默认构造函数注入而言,工厂方法初始化和构造函数自动注入初始化会比较复杂,因为他们构造函数和构造参数的不确定性,Spring 需要花大量的精力来确定构造函数和构造参数,如果确定了则好办,直接选择实例化策略即可。当然在实例化的时候会根据是否有需要覆盖或者动态替换掉的方法,因为存在覆盖或者织入的话需要创建动态代理将方法织入,这个时候就只能选择 CGLIB 的方式来实例化,否则直接利用反射的方式即可。

2.2 属性填充

属性填充其实就是将 BeanDefinition 的属性值赋值给 BeanWrapper 实例对象的过程。在填充的过程需要根据注入的类型不同来区分是根据类型注入还是名字注入,当然在这个过程还会涉及循环依赖的问题的。代码如下:

  1 // AbstractAutowireCapableBeanFactory.java
  2 
  3 protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
  4     // 没有实例化对象
  5     if (bw == null) {
  6         // 有属性,则抛出 BeanCreationException 异常
  7         if (mbd.hasPropertyValues()) {
  8             throw new BeanCreationException(
  9                     mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
 10             // 没有属性,直接 return 返回
 11         } else {
 12             // Skip property population phase for null instance.
 13             return;
 14         }
 15     }
 16 
 17     // <1> 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会
 18     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
 19     // state of the bean before properties are set. This can be used, for example,
 20     // to support styles of field injection.
 21     boolean continueWithPropertyPopulation = true;
 22     if (!mbd.isSynthetic()  // bean 不是"合成"的,即未由应用程序本身定义
 23             && hasInstantiationAwareBeanPostProcessors()) { // 是否持有 InstantiationAwareBeanPostProcessor
 24         // 迭代所有的 BeanPostProcessors
 25         for (BeanPostProcessor bp : getBeanPostProcessors()) {
 26             if (bp instanceof InstantiationAwareBeanPostProcessor) { // 如果为 InstantiationAwareBeanPostProcessor
 27                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
 28                 // 返回值为是否继续填充 bean
 29                 // postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回 true,否则返回 false
 30                 // 一般情况下,应该是返回true 。
 31                 // 返回 false 的话,将会阻止在此 Bean 实例上调用任何后续的 InstantiationAwareBeanPostProcessor 实例。
 32                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
 33                     continueWithPropertyPopulation = false;
 34                     break;
 35                 }
 36             }
 37         }
 38     }
 39     // 如果后续处理器发出停止填充命令,则终止后续操作
 40     if (!continueWithPropertyPopulation) {
 41         return;
 42     }
 43 
 44     // bean 的属性值
 45     PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
 46 
 47     // <2> 自动注入
 48     if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 49         // 将 PropertyValues 封装成 MutablePropertyValues 对象
 50         // MutablePropertyValues 允许对属性进行简单的操作,并提供构造函数以支持Map的深度复制和构造。
 51         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
 52         // Add property values based on autowire by name if applicable.
 53         // 根据名称自动注入
 54         if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
 55             autowireByName(beanName, mbd, bw, newPvs);
 56         }
 57         // Add property values based on autowire by type if applicable.
 58         // 根据类型自动注入
 59         if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
 60             autowireByType(beanName, mbd, bw, newPvs);
 61         }
 62         pvs = newPvs;
 63     }
 64 
 65     // 是否已经注册了 InstantiationAwareBeanPostProcessors
 66     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
 67     // 是否需要进行【依赖检查】
 68     boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
 69 
 70     // <3> BeanPostProcessor 处理
 71     PropertyDescriptor[] filteredPds = null;
 72     if (hasInstAwareBpps) {
 73         if (pvs == null) {
 74             pvs = mbd.getPropertyValues();
 75         }
 76         // 遍历 BeanPostProcessor 数组
 77         for (BeanPostProcessor bp : getBeanPostProcessors()) {
 78             if (bp instanceof InstantiationAwareBeanPostProcessor) {
 79                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
 80                 // 对所有需要依赖检查的属性进行后处理
 81                 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
 82                 if (pvsToUse == null) {
 83                     // 从 bw 对象中提取 PropertyDescriptor 结果集
 84                     // PropertyDescriptor:可以通过一对存取方法提取一个属性
 85                     if (filteredPds == null) {
 86                         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
 87                     }
 88                     pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
 89                     if (pvsToUse == null) {
 90                         return;
 91                     }
 92                 }
 93                 pvs = pvsToUse;
 94             }
 95         }
 96     }
 97     
 98     // <4> 依赖检查
 99     if (needsDepCheck) {
100         if (filteredPds == null) {
101             filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
102         }
103         // 依赖检查,对应 depends-on 属性
104         checkDependencies(beanName, mbd, filteredPds, pvs);
105     }
106 
107     // <5> 将属性应用到 bean 中
108     if (pvs != null) {
109         applyPropertyValues(beanName, mbd, bw, pvs);
110     }
111 }

 

处理流程如下:

  • <1> ,根据 hasInstantiationAwareBeanPostProcessors 属性来判断,是否需要在注入属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会。此过程可以控制 Spring 是否继续进行属性填充。
  • 统一存入到 PropertyValues 中,PropertyValues 用于描述 bean 的属性。
    • <2> ,根据注入类型( AbstractBeanDefinition#getResolvedAutowireMode() 方法的返回值 )的不同来判断:
      • 是根据名称来自动注入(#autowireByName(...)
      • 还是根据类型来自动注入(#autowireByType(...)
    • <3> ,进行 BeanPostProcessor 处理。
    • <4> ,依赖检测。
  • <5> ,将所有 PropertyValues 中的属性,填充到 BeanWrapper 中。

2.3 初始化 bean

初始化 bean 为 #createBean(...) 方法的最后一个过程,代码如下:

 1 // AbstractAutowireCapableBeanFactory.java
 2 
 3 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 4     if (System.getSecurityManager() != null) { // 安全模式
 5         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 6             // <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
 7             invokeAwareMethods(beanName, bean);
 8             return null;
 9         }, getAccessControlContext());
10     } else {
11         // <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
12         invokeAwareMethods(beanName, bean);
13     }
14 
15     // <2> 后处理器,before
16     Object wrappedBean = bean;
17     if (mbd == null || !mbd.isSynthetic()) {
18         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
19     }
20 
21     // <3> 激活用户自定义的 init 方法
22     try {
23         invokeInitMethods(beanName, wrappedBean, mbd);
24     } catch (Throwable ex) {
25         throw new BeanCreationException(
26                 (mbd != null ? mbd.getResourceDescription() : null),
27                 beanName, "Invocation of init method failed", ex);
28     }
29 
30     // <2> 后处理器,after
31     if (mbd == null || !mbd.isSynthetic()) {
32         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
33     }
34 
35     return wrappedBean;
36 }

初始化 bean 的方法其实就是三个步骤的处理,而这三个步骤主要还是根据用户设定的来进行初始化,这三个过程为:

  • <1> 激活 Aware 方法。
  • <3> 后置处理器的应用。
  • <2> 激活自定义的 init 方法。

3. 从 bean 实例中获取对象

无论是从单例缓存中获取的 bean 实例 还是通过 #createBean(...) 方法来创建的 bean 实例,最终都会调用 #getObjectForBeanInstance(...) 方法来根据传入的 bean 实例获取对象,按照 Spring 的传统,该方法也只是做一些检测工作,真正的实现逻辑是委托给 #getObjectFromFactoryBean(...) 方法来实现。代码如下:

 1 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
 2     // <1> 为单例模式且缓存中存在
 3     if (factory.isSingleton() && containsSingleton(beanName)) {
 4         synchronized (getSingletonMutex()) { // <1.1> 单例锁
 5             // <1.2> 从缓存中获取指定的 factoryBean
 6             Object object = this.factoryBeanObjectCache.get(beanName);
 7             if (object == null) {
 8                 // 为空,则从 FactoryBean 中获取对象
 9                 object = doGetObjectFromFactoryBean(factory, beanName);
10                 // 从缓存中获取
11                 // TODO 芋艿,具体原因
12                 // Only post-process and store if not put there already during getObject() call above
13                 // (e.g. because of circular reference processing triggered by custom getBean calls)
14                 Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
15                 if (alreadyThere != null) {
16                     object = alreadyThere;
17                 } else {
18                     // <1.3> 需要后续处理
19                     if (shouldPostProcess) {
20                         // 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
21                         if (isSingletonCurrentlyInCreation(beanName)) {
22                             // Temporarily return non-post-processed object, not storing it yet..
23                             return object;
24                         }
25                         // 单例 Bean 的前置处理
26                         beforeSingletonCreation(beanName);
27                         try {
28                             // 对从 FactoryBean 获取的对象进行后处理
29                             // 生成的对象将暴露给 bean 引用
30                             object = postProcessObjectFromFactoryBean(object, beanName);
31                         } catch (Throwable ex) {
32                             throw new BeanCreationException(beanName,
33                                     "Post-processing of FactoryBean‘s singleton object failed", ex);
34                         } finally {
35                             // 单例 Bean 的后置处理
36                             afterSingletonCreation(beanName);
37                         }
38                     }
39                     // <1.4> 添加到 factoryBeanObjectCache 中,进行缓存
40                     if (containsSingleton(beanName)) {
41                         this.factoryBeanObjectCache.put(beanName, object);
42                     }
43                 }
44             }
45             return object;
46         }
47     // <2>
48     } else {
49         // 为空,则从 FactoryBean 中获取对象
50         Object object = doGetObjectFromFactoryBean(factory, beanName);
51         // 需要后续处理
52         if (shouldPostProcess) {
53             try {
54                 // 对从 FactoryBean 获取的对象进行后处理
55                 // 生成的对象将暴露给 bean 引用
56                 object = postProcessObjectFromFactoryBean(object, beanName);
57             }
58             catch (Throwable ex) {
59                 throw new BeanCreationException(beanName, "Post-processing of FactoryBean‘s object failed", ex);
60             }
61         }
62         return object;
63     }
64 }

 

主要流程如下:

  • 若为单例且单例 Bean 缓存中存在 beanName ,则 <1> 进行后续处理(跳转到下一步),否则,则 <2> 从 FactoryBean 中获取 Bean 实例对象。
  • <1.1> 首先,获取锁。其实我们在前面篇幅中发现了大量的同步锁,锁住的对象都是 this.singletonObjects,主要是因为在单例模式中必须要保证全局唯一。
  • <1.2> 然后,从 factoryBeanObjectCache 缓存中获取实例对象 object 。若 object 为空,则调用 #doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) 方法,从 FactoryBean 获取对象,其实内部就是调用 FactoryBean#getObject() 方法。
  • <1.3> 如果需要后续处理( shouldPostProcess = true ),则进行进一步处理,步骤如下:
    • 若该 Bean 处于创建中(#isSingletonCurrentlyInCreation(String beanName) 方法返回 true ),则返回非处理的 Bean 对象,而不是存储它。
    • 调用 #beforeSingletonCreation(String beanName) 方法,进行创建之前的处理。默认实现将该 Bean 标志为当前创建的。
    • 调用 #postProcessObjectFromFactoryBean(Object object, String beanName) 方法,对从 FactoryBean 获取的 Bean 实例对象进行后置处理。
    • 调用 #afterSingletonCreation(String beanName) 方法,进行创建 Bean 之后的处理,默认实现是将该 bean 标记为不再在创建中。
  • <1.4> 最后,加入到 factoryBeanObjectCache 缓存中。

4. 小结

Spring 加载 bean 的整体过程都已经分析完毕了 深入分析了解 请加qq:1051980588 我们一起来探索

以上是关于IoC 之加载 Bean:总结的主要内容,如果未能解决你的问题,请参考以下文章

死磕 Spring----- IOC 之加载 bean:总结

[死磕 Spring 3/43] --- IOC 之 加载 Bean

面试必会必知:Spring IoC 之 加载 Bean

[死磕 Spring 16/43] --- IOC 之开启 bean 的加载

spring源码深度解析— IOC 之 开启 bean 的加载

死磕 Spring----- IOC 之开启 bean 的加载