Spring IoC源码学习:finishBeanFactoryInitialization 详解

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在介绍了obtainFreshBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors 三个重要方法后,我们终于来到了最后一个重要方法:finishBeanFactoryInitialization。finishBeanFactoryInitialization是这四个方法中最复杂也是最重要的,是整个 Spring IoC 核心中的核心。

目录

Spring IoC源码学习全系列

前言

概述

正文

finishBeanFactoryInitialization

MergedBeanDefinition

代码块1preInstantiateSingletons

代码块2getMergedLocalBeanDefinition

代码块3getMergedBeanDefinition

代码块4transformedBeanName

FactoryBean

代码块5getMergedBeanDefinition

BeanFactory

代码块6isFactoryBean

代码块7getSingleton

代码块8isFactoryBean

代码块9predictBeanType

总结

相关文章


Spring IoC源码学习全系列

小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习ApplicationContext 刷新前的配置

Spring IoC源码学习obtainFreshBeanFactory详解

Spring IoC码学习parseDefaultElement详解

Spring IoC源码学习parseCustomElement详解

Spring IoC源码学习:context:component-scan 节点详解

Spring IoC源码学习invokeBeanFactoryPostProcessors详解

Spring IoC源码学习registerBeanPostProcessors详解

Spring IoC源码学习finishBeanFactoryInitialization详解

Spring IoC源码学习getBean详解

Spring IoC源码学习createBean详解(上)

Spring IoC源码学习createBean详解(下)

Spring IoC源码学习:@Autowire 详解

Spring IoC源码学习:finishRefresh 详解

 

前言


在介绍了obtainFreshBeanFactoryinvokeBeanFactoryPostProcessorsregisterBeanPostProcessors 三个重要方法后,我们终于来到了最后一个重要方法:finishBeanFactoryInitializationfinishBeanFactoryInitialization是这四个方法中最复杂也是最重要的,是整个 Spring IoC 核心中的核心。

 

概述


该方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了BeanFactoryPostProcessor 接口的 bean、实现了BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。

 

正文


首先我们回到 AbstractApplicationContext.refresh()方法,找到代码:finishBeanFactoryInitialization(beanFactory),单击该行代码跳转到具体的实现。

 

finishBeanFactoryInitialization


protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 1.初始化此上下文的转换服务
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    // 2.如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器:主要用于注解属性值的解析。
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
            @Override
            public String resolveStringValue(String strVal) {
                return getEnvironment().resolvePlaceholders(strVal);
            }
        });
    }
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    // 3.初始化LoadTimeWeaverAware Bean实例对象
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // Stop using the temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(null);
    // Allow for caching all bean definition metadata, not expecting further changes.
    // 4.冻结所有bean定义,注册的bean定义不会被修改或进一步后处理,因为马上要创建 Bean 实例对象了
    beanFactory.freezeConfiguration();
    // Instantiate all remaining (non-lazy-init) singletons.
    // 5.实例化所有剩余(非懒加载)单例对象
    beanFactory.preInstantiateSingletons();
}

5.实例化所有剩余(非懒加载)单例对象,见代码块1详解

 

MergedBeanDefinition


在之后的内容你可能会频繁的见到 “MergedBeanDefinition” 这个词,因此这边先稍微讲解一下,有助于你更好的理解。


MergedBeanDefinition:这个词其实不是一个官方词,但是很接近,该词主要是用来表示合并的bean 定义,因为每次都写合并的 bean 定义有点太绕口,因此我在之后的注释或解析中或统一使用 MergedBeanDefinition 来表示合并的bean 定义

之所以称之为合并的,是因为存在子定义父定义的情况。对于一个 bean 定义来说,可能存在以下几种情况:


1.     BeanDefinition 存在父定义:首先使用父定义的参数构建一个 RootBeanDefinition,然后再使用该 BeanDefinition 的参数来进行覆盖。

2.     BeanDefinition 不存在父定义,并且该 BeanDefinition 的类型是 RootBeanDefinition:直接返回该 RootBeanDefinition 的一个克隆。

3.     BeanDefinition 不存在父定义,但是该 BeanDefinition 的类型不是 RootBeanDefinition:使用该BeanDefinition 的参数构建一个 RootBeanDefinition

之所以区分出23,是因为通常 BeanDefinition 在之前加载到 BeanFactory中的时候,通常是被封装成 GenericBeanDefinition ScannedGenericBeanDefinition,但是从这边之后 bean 的后续流程处理都是针对 RootBeanDefinition,因此在这边会统一将 BeanDefinition 转换成 RootBeanDefinition


在我们日常使用的过程中,通常会是上面的第3种情况。如果我们使用 XML 配置来注册 bean,则该 bean 定义会被封装成:GenericBeanDefinition;如果我们使用注解的方式来注册 bean,也就是<context:component-scan /> + @Compoment,则该 bean 定义会被封装成 ScannedGenericBeanDefinition

 

代码块1preInstantiateSingletons


@Override
public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Pre-instantiating singletons in " + this);
    }
    // Iterate over a copy to allow for init methods which in turn register new bean definitions.
    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
    // 1.创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singleton beans...
    // 2.遍历beanNames,触发所有非懒加载单例bean的初始化
    for (String beanName : beanNames) {
        // 3.获取beanName对应的MergedBeanDefinition
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 4.bd对应的Bean实例:不是抽象类 && 是单例 && 不是懒加载
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 5.判断beanName对应的bean是否为FactoryBean
            if (isFactoryBean(beanName)) {
                // 5.1 通过beanName获取FactoryBean实例
                // 通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                // 5.2 判断这个FactoryBean是否希望急切的初始化
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                } else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    // 5.3 如果希望急切的初始化,则通过beanName获取bean实例
                    getBean(beanName);
                }
            } else {
                // 6.如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
                getBean(beanName);
            }
        }
    }
    // Trigger post-initialization callback for all applicable beans...
    // 7.遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
    for (String beanName : beanNames) {
        // 7.1 拿到beanName对应的bean实例
        Object singletonInstance = getSingleton(beanName);
        // 7.2 判断singletonInstance是否实现了SmartInitializingSingleton接口
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            // 7.3 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            } else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

3.获取 beanName 对应的 MergedBeanDefinition见代码块2详解。

5.判断 beanName 对应的 bean 是否为FactoryBean见代码块6详解

5.3 6. 通过beanName 获取 bean 实例,finishBeanFactoryInitialization 方法的核心,限于篇幅,在下一篇文章开始介绍

7.遍历 beanNames,触发所有 SmartInitializingSingleton 的后初始化回调,这是 Spring 提供的一个扩展点,在所有非懒加载单例实例化结束后调用。

 

代码块2getMergedLocalBeanDefinition

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // Quick check on the concurrent map first, with minimal locking.
    // 1.检查beanName对应的MergedBeanDefinition是否存在于缓存中
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    if (mbd != null) {
        // 2.如果存在于缓存中则直接返回
        return mbd;
    }
    // 3.如果不存在于缓存中
    // 3.1 getBeanDefinition(beanName): 获取beanName对应的BeanDefinition,从beanDefinitionMap缓存中获取
    // 3.2 getMergedBeanDefinition: 根据beanName和对应的BeanDefinition,获取MergedBeanDefinition
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

3.2 根据 beanName beanName 对应的 BeanDefinition,获取 MergedBeanDefinition见代码块3详解

 

代码块3getMergedBeanDefinition

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
        throws BeanDefinitionStoreException {
    return getMergedBeanDefinition(beanName, bd, null);
}
protected RootBeanDefinition getMergedBeanDefinition(
        String beanName, BeanDefinition bd, BeanDefinition containingBd)
        throws BeanDefinitionStoreException {
    // 1.加锁再进行操作
    synchronized (this.mergedBeanDefinitions) {
        // 用于存储bd的MergedBeanDefinition,也就是该方法的结果
        RootBeanDefinition mbd = null;
        // Check with full lock now in order to enforce the same merged instance.
        if (containingBd == null) {
            // 2.检查beanName对应的MergedBeanDefinition是否存在于缓存中
            mbd = this.mergedBeanDefinitions.get(beanName);
        }
        // 3.如果beanName对应的MergedBeanDefinition不存在于缓存中
        if (mbd == null) {
            if (bd.getParentName() == null) {
                // 4.如果bd的parentName为空,代表bd没有父定义,无需与父定义进行合并操作,
                // 也就是bd的MergedBeanDefinition就是bd本身(可能需要转成RootBeanDefinition)
                // Use copy of given root bean definition.
                if (bd instanceof RootBeanDefinition) {
                    // 4.1 如果bd的类型为RootBeanDefinition,则bd的MergedBeanDefinition就是bd本身,则直接克隆一个副本
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                } else {
                    // 4.2 否则,将bd作为参数,构建一个RootBeanDefinition。
                    // 正常使用下,BeanDefinition在被加载后是GenericBeanDefinition或ScannedGenericBeanDefinition
                    mbd = new RootBeanDefinition(bd);
                }
            } else {
                // 5.否则,bd存在父定义,需要与父定义合并
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    // 5.1 获取父定义的beanName
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    // 5.2 如果父定义的beanName与该bean的beanName不同
                    if (!beanName.equals(parentBeanName)) {
                        // 5.3 获取父定义的MergedBeanDefinition(因为父定义也可能有父定义,也就是bd的爷爷定义...)
                        pbd = getMergedBeanDefinition(parentBeanName);
                    } else {
                        // 5.4 如果父定义的beanName与bd的beanName相同,则拿到父BeanFactory,
                        // 只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            // 5.5 如果父BeanFactory是ConfigurableBeanFactory,则通过父BeanFactory获取父定义的MergedBeanDefinition
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        } else {
                            // 5.6 如果父BeanFactory不是ConfigurableBeanFactory,则抛异常
                            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.
                // 5.7 使用父定义pbd构建一个新的RootBeanDefinition对象(深拷贝)
                mbd = new RootBeanDefinition(pbd);
                // 5.8 使用bd覆盖父定义
                mbd.overrideFrom(bd);
            }
            // Set default singleton scope, if not configured before.
            // 6.如果没有配置scope,则设置成默认的singleton
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.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.
            // 7.如果containingBd不为空 && containingBd不为singleton && mbd为singleton,则将mdb的scope设置为containingBd的scope
            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)
            // 8.将beanName与mbd放到mergedBeanDefinitions缓存,以便之后可以直接使用
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }
        // 9.返回MergedBeanDefinition
        return mbd;
    }
}

5.1 获取父定义的 beanName,这边有一个beanName 的转换操作,之后会经常用到,见代码块4详解

5.3 获取父定义的 MergedBeanDefinition见代码块5详解

5.7 5.8 就是合并操作,也就是我们之前一直说的 MergedBeanDefinition 的由来。

8.将该 beanName MergedBeanDefinition 放到mergedBeanDefinitions 缓存,后续再走到代码块2时,就会直接返回缓存里的数据。

 

代码块4transformedBeanName

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    String beanName = name;
    // 如果beanName带有 "&" 前缀,则去掉
    while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    }
    return beanName;
}
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 将别名解析成真正的beanName
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

name 真正解析成真正的 beanName,主要是去掉 FactoryBean 里的“&” 前缀,和解析别名。这边简单的介绍下 FactoryBean

 

FactoryBean


一般情况下,Spring 通过反射机制利用 bean  class 属性指定实现类来实例化 bean。而 FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject()方法。

注:很多中间件都利用 FactoryBean 来进行扩展。

例如以下例子:

public class AppleFactoryBean implements FactoryBean<Apple> {
    @Override
    public Apple getObject() throws Exception {
        Apple apple = new Apple();
        apple.setName("bigApple");
        return apple;
    }
    @Override
    public Class<?> getObjectType() {
        return Apple.class;
    }
    @Override
    public boolean isSingleton() {
        return true;
    }
}

为了区分“FactoryBean” “FactoryBean 创建的 bean实例Spring 使用了 “&” 前缀。假设我们的 beanName apple,则 getBean("apple") 获得的是 AppleFactoryBean 通过 getObject()方法创建的 bean 实例;而getBean("&apple") 获得的是 AppleFactoryBean 本身。

 

代码块5getMergedBeanDefinition

@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
    // 1.获取真正的beanName(解析别名)
    String beanName = transformedBeanName(name);
    // Efficiently check whether bean definition exists in this factory.
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
        // 2.如果当前BeanFactory中不存在beanName的Bean定义 && 父beanFactory是ConfigurableBeanFactory,
        // 则调用父BeanFactory去获取beanName的MergedBeanDefinition
        return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
    }
    // Resolve merged bean definition locally.
    // 3.在当前BeanFactory中解析beanName的MergedBeanDefinition
    return getMergedLocalBeanDefinition(beanName);
}

这边引入了一个 BeanFactory” 的概念,稍微解释下。

 

BeanFactory


Spring 中可能存在多个 BeanFactory,多个 BeanFactory 可能存在父工厂子工厂的关系。最常见的例子就是:Spring MVC BeanFactory Spring BeanFactory,通常情况下,Spring BeanFactory 父工厂Spring MVC BeanFactory 子工厂,在 Spring 中,子工厂可以使用父工厂的 BeanDefinition,因而,如果在当前 BeanFactory 中找不到,而又存在父工厂,则会去父工厂中查找。

 

代码块6isFactoryBean

@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
    // 1.拿到真正的beanName(去掉&前缀、解析别名)
    String beanName = transformedBeanName(name);
    // 2.尝试从缓存获取Bean实例对象
    Object beanInstance = getSingleton(beanName, false);
    if (beanInstance != null) {
        // 3.beanInstance存在,则直接判断类型是否为FactoryBean
        return (beanInstance instanceof FactoryBean);
    } else if (containsSingleton(beanName)) {
        // 4.如果beanInstance为null,并且beanName在单例对象缓存中,则代表beanName对应的单例对象为空对象,返回false
        // null instance registered
        return false;
    }
    // No singleton instance found -> check bean definition.
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
        // 5.如果缓存中不存在此beanName && 父beanFactory是ConfigurableBeanFactory,则调用父BeanFactory判断是否为FactoryBean
        // No bean definition found in this factory -> delegate to parent.
        return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
    }
    // 6.通过MergedBeanDefinition来检查beanName对应的Bean是否为FactoryBean
    return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}

2.尝试从缓存获取 bean 实例对象,见代码块7详解

6.通过 MergedBeanDefinition 来检查 beanName 对应的bean 是否为 FactoryBean。首先通过 getMergedLocalBeanDefinition 方法获取beanName MergedBeanDefinition,该方法在代码块2已经解析过;接着调用 isFactoryBean 来检查 beanName 对应的 bean 是否为 FactoryBean见代码块8详解

 

代码块7getSingleton

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 1.从单例对象缓存中获取beanName对应的单例对象
    Object singletonObject = this.singletonObjects.get(beanName);
    // 2.如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 3.加锁进行操作
        synchronized (this.singletonObjects) {
            // 4.从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
            // 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 5.如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
            if (singletonObject == null && allowEarlyReference) {
                // 6.从单例工厂缓存中获取beanName的单例工厂
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 7.如果存在单例对象工厂,则通过工厂创建一个单例对象
                    singletonObject = singletonFactory.getObject();
                    // 8.将通过单例对象工厂创建的单例对象,放到早期单例对象缓存中
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 9.移除该beanName对应的单例对象工厂,因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存了,
                    // 因此,后续获取beanName的单例对象,可以通过earlySingletonObjects缓存拿到,不需要在用到该单例工厂
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    // 10.返回单例对象
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

这段代码很重要,在正常情况下,该代码很普通,只是正常的检查下我们要拿的 bean 实例是否存在于缓存中,如果有就返回缓存中的 bean 实例,否则就返回 null


这段代码之所以重要,是因为该段代码是 Spring 解决循环引用的核心代码。


解决循环引用逻辑:使用构造函数创建一个不完整 bean 实例(之所以说不完整,是因为此时该 bean 实例还未初始化),并且提前曝光该 bean 实例的ObjectFactory(提前曝光就是将 ObjectFactory 放到 singletonFactories 缓存),通过ObjectFactory 我们可以拿到该 bean 实例的引用,如果出现循环引用,我们可以通过缓存中的 ObjectFactory 来拿到 bean 实例,从而避免出现循环引用导致的死循环。这边通过缓存中的 ObjectFactory 拿到的 bean 实例虽然拿到的是不完整 bean 实例,但是由于是单例,所以后续初始化完成后,该 bean 实例的引用地址并不会变,所以最终我们看到的还是完整 bean 实例。


这段解决逻辑涉及到了后面的一些内容,所以可能会看的不是很理解,可以先有个印象,等把创建 bean 实例都看完了,再回过头来看,可能会好理解一点。


另外这个代码块中引进了4个重要缓存:


1.    singletonObjects 缓存:beanName -> 单例 bean 对象。

2.    earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。

3.    singletonFactories 缓存:beanName -> ObjectFactory

4.    singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。

singletonObjectsearlySingletonObjectssingletonFactories 在这边构成了一个类似于三级缓存的概念。

 

代码块8isFactoryBean


protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
    // 1.拿到beanName对应的Bean实例的类型
    Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
    // 2.返回beanType是否为FactoryBean本身、子类或子接口
    return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
}

1.拿到 beanName 对应的 bean 实例的类型,见代码块9详解

 

代码块9predictBeanType

@Override
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
    // 1.拿到beanName的类型
    Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
    // Apply SmartInstantiationAwareBeanPostProcessors to predict the
    // eventual type after a before-instantiation shortcut.
    // 2.应用SmartInstantiationAwareBeanPostProcessors后置处理器,来预测实例化的最终类型,
    // SmartInstantiationAwareBeanPostProcessors继承了InstantiationAwareBeanPostProcessor,
    // InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法可以改变Bean实例的类型,
    // 而SmartInstantiationAwareBeanPostProcessors的predictBeanType方法可以预测这个类型
    if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                // 3.调用predictBeanType方法
                Class<?> predicted = ibp.predictBeanType(targetType, beanName);
                if (predicted != null && (typesToMatch.length != 1 || FactoryBean.class != typesToMatch[0] ||
                        FactoryBean.class.isAssignableFrom(predicted))) {
                    // 4.如果predicted不为空 && (typesToMatch长度不为1 || typesToMatch[0]不为FactoryBean.class ||
                    // predicted是FactoryBean本身、子类或子接口),则返回predicted
                    return predicted;
                }
            }
        }
    }
    // 5.否则返回beanName的类型
    return targetType;
}

这边走的是 AbstractAutowireCapableBeanFactory 里的方法,而不是 AbstractBeanFactory 里的方法。通过前面的介绍,我们知道创建的 BeanFactory DefaultListableBeanFactory,而DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory,因此这边会走 AbstractAutowireCapableBeanFactory的重写方法。

 

总结


本文执行了创建bean 实例前的一些准备操作。主要是引入了 FactoryBean 这一特殊的 bean,获取 BeanDefinition MergedBeanDefinition,最后将 BeanDefinition 统一转换成 RootBeanDefinition


另外,本文还引入了几个重要的缓存,如下:


·       mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。

·       beanDefinitionMap 缓存:beanName -> BeanDefinition

·       singletonObjects 缓存:beanName -> 单例 bean 对象。

·       earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。

·       singletonFactories 缓存:beanName -> ObjectFactory

·       singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。

Spring 中大量使用了本地缓存,基本上通过名字和注释就能理解缓存的作用了。在下一篇文章中,我们将正式进入 bean 实例的获取。

 

相关文章



Spring IoC:源码学习总览

Spring IoCApplicationContext 刷新前的配置

Spring IoCobtainFreshBeanFactory详解

Spring IoCparseDefaultElement详解

Spring IoCparseCustomElement详解

Spring IoCcontext:component-scan节点详解

Spring IoCinvokeBeanFactoryPostProcessors详解

Spring IoCregisterBeanPostProcessors详解

 

相关文章
|
5天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
19 2
|
22天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
11天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
37 9
|
20天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
35 9
|
1月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
20 1
|
12天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
25 0
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
61 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
92 1
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
26 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现