注:《Spring5源码分析》汇总可参考:Spring5源码分析(002)——博客汇总
- 1、从父工厂 parentBeanFactory 中进行加载 :如果当前 BeanFactory 的 beanDefinitionMap 中没有相关的 BeanDefinition 定义且存在父工厂时,则通过父工厂 parentBeanFactory 来获取 bean 实例,此时是递归调用 #getBean 的各个重载方法来处理
- 2、在当前 BeanFactory 中,根据各种 scope 进行 bean 实例化,此时还需要处理的就是相关的依赖 bean ,他们都需要提前实例化。也即是先实例化依赖,然后再根据不同的 scope 来进行实际的实例化。
- 第一部分,主要是一些前置检测、通过 parentBeanFactory 获取 bean 实例、依赖 bean 处理,前文中提到的 2.4 - 2.8
- 第二部分,则是根据各种 scope 进行 bean 的实例化
/// org.springframework.beans.factory.support.AbstractBeanFactory /// protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) // 其他处理代码。。。 // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // 4、原型模式的依赖检查 // 只有在单例情况下才会尝试解决循环依赖,原型模式情况下,如果存在 A 中有 B 的属性, B 中有 A 的属性, // 那么当依赖注入的时候,就会产生A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是下面的情况。 // 原型模式下如果存在循环依赖则会抛出异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 5、检查 parentBeanFactory 是否存在对应的 bean // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); // 当前容器中没有找到,则从父类容器中加载 // 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName 指定的 bean, // 则尝试从 parentBeanFactory 中检测 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); // 递归到 BeanFactory 中寻找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // 6、如果不是仅仅做类型检查则是创建 bean ,这里需要进行记录 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 7、将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition , // 如果指定的 beanName 是子 bean 的话同时会合并父类的相关属性 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 8、处理依赖的 bean // Guarantee initialization of beans that the current bean depends on. // 若存在依赖则需要递归实例化依赖的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 循环依赖的情况,depends-on 是强制依赖 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 缓存依赖调用 registerDependentBean(dep, beanName); try { // 递归调用获取依赖的 bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } /// 其他处理代码。。。
结合注释可以看出,这段代码主要处理以下这几个部分:
- 4、原型模式的依赖检测,原型模式下如果检测到循环依赖,即当前 bean 正在创建中,则抛出 BeanCurrentlyInCreationException 异常,具体分析参考【1、原型模式的依赖检测】
- 5、检查 parentBeanFactory 是否存在对应的 bean ,如果当前 BeanFactory 的 beanDefinitionMap 中没有相关的 BeanDefinition 定义且存在父工厂时,则通过父工厂 parentBeanFactory 来获取 bean 实例,具体分析参考【2、检查 parentBeanFactory 是否存在对应的 bean】
- 6、类型检查,将指定的 bean 标记为已创建或即将创建,具体分析参考【3、类型检查】
- 7、将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition,具体分析参考【4、将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition】
- 8、依赖处理,具体分析参考【5、依赖处理】
1、原型模式的依赖检测
/// org.springframework.beans.factory.support.AbstractBeanFactory // Fail if we're already creating this bean instance: // We're assumably within a circular reference. // 4、原型模式的依赖检查 // 只有在单例情况下才会尝试解决循环依赖,原型模式情况下,如果存在 A 中有 B 的属性, B 中有 A 的属性, // 那么当依赖注入的时候,就会产生A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是下面的情况。 // 原型模式下如果存在循环依赖则会抛出异常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } /// /** * Return whether the specified prototype bean is currently in creation * (within the current thread). * @param beanName the name of the bean */ protected boolean isPrototypeCurrentlyInCreation(String beanName) { Object curVal = this.prototypesCurrentlyInCreation.get(); return (curVal != null && (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); } /** Names of beans that are currently in creation. */ private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation");
可以看到循环依赖的检测判断有些似曾相识,都是通过正在创建中的集合来判断的,也就是创建时记录和检查,这里是通过 prototypesCurrentlyInCreation 这个 ThreadLocal 来进行记录相关的创建中原型集合的,而这个记录则是在 beforePrototypeCreation(String beanName) 和 afterPrototypeCreation(String beanName) ,这个可以在稍后面的原型实例化创建时看到有相关调用,这里的默认实现就是直接将 beanName 丢到 prototypesCurrentlyInCreation 中。
2、检查 parentBeanFactory 是否存在对应的 bean
如果当前 BeanFactory 的 beanDefinitionMap 中没有相关的 BeanDefinition 定义,也就是说通过 # containsBeanDefinition(String beanName) 方法获不到对应的bean定义,且存在父工厂时,则通过父工厂 parentBeanFactory 来获取 bean 实例,代码如下:
/// org.springframework.beans.factory.support.AbstractBeanFactory // 5、检查 parentBeanFactory 是否存在对应的 bean // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); // 当前容器中没有找到,则从父类容器中加载 // 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName 指定的 bean, // 则尝试从 parentBeanFactory 中检测 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); // 递归到 BeanFactory 中寻找 if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } }
这过程其实也好理解,就是递归调用 #getBean 方法来获取实例。需要注意的是,这里的 beanName 是需要做转换的,调用 #originalBeanName(String name) 来处理,代码如下:
/** * Determine the original bean name, resolving locally defined aliases to canonical names. * @param name the user-specified name * @return the original bean name */ protected String originalBeanName(String name) { String beanName = transformedBeanName(name); if (name.startsWith(FACTORY_BEAN_PREFIX)) { beanName = FACTORY_BEAN_PREFIX + beanName; } return beanName; }
3、类型检查
/// org.springframework.beans.factory.support.AbstractBeanFactory /** * Mark the specified bean as already created (or about to be created). * <p>This allows the bean factory to optimize its caching for repeated * creation of the specified bean. * <p>将指定的 bean 标记为已创建或即将创建。 * <p>这允许 beanFactory 优化其缓存,以重复创建指定的Bean。 * @param beanName the name of the bean */ protected void markBeanAsCreated(String beanName) { // 还没有创建 if (!this.alreadyCreated.contains(beanName)) { // 加锁 synchronized (this.mergedBeanDefinitions) { // DCL 双重检查 if (!this.alreadyCreated.contains(beanName)) { // Let the bean definition get re-merged now that we're actually creating // the bean... just in case some of its metadata changed in the meantime. clearMergedBeanDefinition(beanName); // 添加到已创建 bean 集合中 this.alreadyCreated.add(beanName); } } } } /** * Remove the merged bean definition for the specified bean, * recreating it on next access. * <p>从 mergedBeanDefinitions 中删除指定的 bean ,并在下次访问时重新创建它。 * @param beanName the bean name to clear the merged definition for */ protected void clearMergedBeanDefinition(String beanName) { RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName); if (bd != null) { bd.stale = true; } }
4、将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition
/// org.springframework.beans.factory.support.AbstractBeanFactory // 7、将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition , // 如果指定的 beanName 是子 bean 的话同时会合并父类的相关属性 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args);
- 1、这里首先调用 #getMergedLocalBeanDefinition(String beanName) 方法,获取 BeanDefinition 对象,代码如下:
/// org.springframework.beans.factory.support.AbstractBeanFactory /** * Return a merged RootBeanDefinition, traversing the parent bean definition * if the specified bean corresponds to a child bean definition. * <p>将存储 XML 配置的 GenericBeanDefinition 转换成 RootBeanDefinition , * 如果指定的 beanName 是子bean的话同时会合并父类的相关属性 * @param beanName the name of the bean to retrieve the merged definition for * @return a (potentially merged) RootBeanDefinition for the given bean * @throws NoSuchBeanDefinitionException if there is no bean with the given name * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { // Quick check on the concurrent map first, with minimal locking. RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); if (mbd != null && !mbd.stale) { return mbd; } return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); } /** * Return a RootBeanDefinition for the given top-level bean, by merging with * the parent if the given bean's definition is a child bean definition. * <p>返回给定顶层 bean 的 RootBeanDefinition ,如果给定的 bean 定义是 * 子 bean 定义,则会同时合并父bean定义 * @param beanName the name of the bean definition * @param bd the original bean definition (Root/ChildBeanDefinition) * @return a (potentially merged) RootBeanDefinition for the given bean * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) throws BeanDefinitionStoreException { return getMergedBeanDefinition(beanName, bd, null); } /** * Return a RootBeanDefinition for the given bean, by merging with the * parent if the given bean's definition is a child bean definition. * @param beanName the name of the bean definition * @param bd the original bean definition (Root/ChildBeanDefinition) * @param containingBd the containing bean definition in case of inner bean, * or {@code null} in case of a top-level bean * @return a (potentially merged) RootBeanDefinition for the given bean * @throws BeanDefinitionStoreException in case of an invalid bean definition */ protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) throws BeanDefinitionStoreException { // 同步锁 synchronized (this.mergedBeanDefinitions) { RootBeanDefinition mbd = null; RootBeanDefinition previous = null; // Check with full lock now in order to enforce the same merged instance. // 同步锁下重新获取,确保是同一个合并实例对象 if (containingBd == null) { mbd = this.mergedBeanDefinitions.get(beanName); } // 需要合并/重新合并 if (mbd == null || mbd.stale) { previous = mbd; // 没有父bean if (bd.getParentName() == null) { // Use copy of given root bean definition. if (bd instanceof RootBeanDefinition) { mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); } else { mbd = new RootBeanDefinition(bd); } } else { // 需要合并父bean定义 // Child bean definition: needs to be merged with parent. BeanDefinition pbd; try { String parentBeanName = transformedBeanName(bd.getParentName()); if (!beanName.equals(parentBeanName)) { pbd = getMergedBeanDefinition(parentBeanName); } else { BeanFactory parent = getParentBeanFactory(); if (parent instanceof ConfigurableBeanFactory) { pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); } else { throw new NoSuchBeanDefinitionException(parentBeanName, "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + "': cannot be resolved without an AbstractBeanFactory parent"); } } } catch (NoSuchBeanDefinitionException ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); } // Deep copy with overridden values. mbd = new RootBeanDefinition(pbd); mbd.overrideFrom(bd); } // Set default singleton scope, if not configured before. // 设置默认 scope if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(SCOPE_SINGLETON); } // A bean contained in a non-singleton bean cannot be a singleton itself. // Let's correct this on the fly here, since this might be the result of // parent-child merging for the outer bean, in which case the original inner bean // definition will not have inherited the merged outer bean's singleton status. if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { mbd.setScope(containingBd.getScope()); } // Cache the merged bean definition for the time being // (it might still get re-merged later on in order to pick up metadata changes) if (containingBd == null && isCacheBeanMetadata()) { this.mergedBeanDefinitions.put(beanName, mbd); } } if (previous != null) { copyRelevantMergedBeanDefinitionCaches(previous, mbd); } return mbd; } }
-
- 先从缓存 mergedBeanDefinitions 中获取 RootBeanDefinition 对象,如果存在且不需要重新合并,则直接返回;
- 否则调用 #getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 获取。前面从 bean 的解析过程中我们可以知道,从 xml 配置文件中读取到的 bean 信息是存储在 GenericBeanDefinition 中的,而 Spring 中所有的 bean 后续的处理都是针对 RootBeanDefinition 的,因此这里需要进行一个转换,转换的同时如果父类 bean 不为空的话,则会一并合并父类的属性,感兴趣的可以进一步深入研究。
- 2、调用 #checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) 方法,对 RootBeanDefinition 进行校验,这里只是检查是否是抽象类。
/** * Check the given merged bean definition, * potentially throwing validation exceptions. * @param mbd the merged bean definition to check * @param beanName the name of the bean * @param args the arguments for bean creation, if any * @throws BeanDefinitionStoreException in case of validation failure */ protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) throws BeanDefinitionStoreException { if (mbd.isAbstract()) { throw new BeanIsAbstractException(beanName); } }
5、依赖处理
如果需要获取的 bean 有依赖,则需要确保相关依赖先初始化,代码如下:
// 8、处理依赖的 bean // Guarantee initialization of beans that the current bean depends on. // 若存在依赖则需要递归实例化依赖的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 循环依赖的情况,depends-on 是强制依赖 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 缓存依赖调用 registerDependentBean(dep, beanName); try { // 递归调用获取依赖的 bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } }
主要逻辑还是循环依赖检测、缓存注册,然后递归调用 #getBean 方法进行 bean 依赖的实例化。
5.1、isDependent
该方法用于确定指定的依赖Bean是否已注册为依赖于给定Bean或依赖于其任何传递依赖项,递归检测,其实就是循环依赖检测,因为 depends-on 是强制依赖,不能有循环依赖。
/// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry /** Map between dependent bean names: bean name to Set of dependent bean names. * <p>存放映射关系(依赖谁集合): beanName --> 依赖的 beanNames 集合,即 [canonicalName --> dependentBeanName set] */ private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); /** * Determine whether the specified dependent bean has been registered as * dependent on the given bean or on any of its transitive dependencies. * <p>确定指定的依赖Bean是否已注册为依赖于给定Bean或依赖于其任何传递依赖项。 * @param beanName the name of the bean to check * @param dependentBeanName the name of the dependent bean * @since 4.0 */ protected boolean isDependent(String beanName, String dependentBeanName) { synchronized (this.dependentBeanMap) { return isDependent(beanName, dependentBeanName, null); } } private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) { if (alreadySeen != null && alreadySeen.contains(beanName)) { return false; } // 获取真正的 beanName String canonicalName = canonicalName(beanName); // 当前 beanName 依赖的bean集合 Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { return false; } // 存在则说明存在循环依赖 if (dependentBeans.contains(dependentBeanName)) { return true; } // 对所有依赖进行递归检测 for (String transitiveDependency : dependentBeans) { if (alreadySeen == null) { alreadySeen = new HashSet<>(); } // 添加到 alreadySeen 中 alreadySeen.add(beanName); // 递归调用检测 if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } return false; }
5.2、registerDependentBean
为给定的 bean 注册一个依赖 bean,在销毁指定的 bean 之前销毁该 bean,其实就是记录“谁依赖哪些谁”、“谁被哪些谁依赖”之间的映射。需要说明的是, depends-on 是一种强制依赖初始化,不能有循环依赖,因此这里进行了注册判断。代码如下:
/** * Register a dependent bean for the given bean, * to be destroyed before the given bean is destroyed. * <p>为给定的 bean 注册一个依赖 bean,在销毁指定的 bean 之前销毁该 bean * @param beanName the name of the bean * @param dependentBeanName the name of the dependent bean */ public void registerDependentBean(String beanName, String dependentBeanName) { // 获取真正的 beanName String canonicalName = canonicalName(beanName); // 添加 [canonicalName --> dependentBeanName set] 到 dependentBeanMap 中 synchronized (this.dependentBeanMap) { Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8)); if (!dependentBeans.add(dependentBeanName)) { return; } } // 添加 [dependentBeanName --> canonicalName set] 到 dependenciesForBeanMap 中 synchronized (this.dependenciesForBeanMap) { Set<String> dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8)); dependenciesForBean.add(canonicalName); } }
5.3、getBean
这里就是通过递归调用 #getBean 方法实例化依赖的 bean 。
6、参考
- [1]spring 官方文档 5.2.3.RELEASE:https://docs.spring.io/spring-framework/docs/5.2.3.RELEASE/spring-framework-reference/core.html
- [2]Spring源码深度解析(第2版)
- [3]相关注释和案例可参考笔者 github 链接:https://github.com/wpbxin/spring-framework