【六】Spring IoC 最全源码详解之bean实例化过程

如果将Spring初始化过程中创建bean之前的准备工作比喻成生命从无到有,从单细胞生命变为多细胞生命,从海洋蔓延到陆地,从……的话,那么本章即将介绍的bean实例化过程就是寒武纪生命大爆发!


目录

1.getBean

2.createBean

3.createBeanInstance

3.1 寻找构造函数进行实例化

3.1.1 利用默认构造函数实例化

3.1.2 利用带参构造函数实例化

4.相亲算法

5. 附录:本项目工程文件


本节介绍bean实例化过程。对应执行的方法是finishBeanFactoryInitialization(beanFactory),中间跳过的国际化和事件监听器注册与初始化的步骤后续再专门写文章补充。本章节撰写时长12小时,建议阅读时常:6小时。去趟卫生间,等你回来我们就开始吧。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    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));
    }

    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    
    beanFactory.setTempClassLoader(null);
    // “冻结”住所有已经注册在bean工厂中的bd元数据,避免被改变了。
    beanFactory.freezeConfiguration();
    // 真正的干货所在
    beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons()方法主要可以分两个阶段:1.对所有非lazy的bean进行创建;2.执行某些特殊bean创建完成后的回调方法。

public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    // 遍历所有beanName,对所有的non-lazy且singletonbean进行创建,已经创建的不会再次执行。
    for (String beanName : beanNames) {
    	// 该方法的merge是指如果bean类继承有父类,那么就将它所有的父类的bd融合成一个RootBeanDefinition返回
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        //bean不是抽象的,没有@Lazy注解,并且还是单例的
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            //如果是FactoryBean,前面文章有提到过,FactoryBean的名字命名规则是:& + 普通beanName,获取到正确的名称后才能做getBean(beanName)这一步
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                        ((SmartFactoryBean<?>) factory)::isEagerInit,
                                getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // 完成所有bean的创建过程后,执行实现了SmartInitializingSingleton接口bean的afterSingletonsInstantiated回调方法。
    // org.springframework.boot.autoconfigure.condition.BeanTypeRegistry会清空bdmap
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

首先从bean工厂的bdmap中拿到所有的beanName,然后对其中能实例化的bean进行创建。getMergedLocalBeanDefinitio(beanName)是后续中经常会用到的方法,它的作用是从本bd出发,合并继承路径上的所有bd,合并完成后还要将合成后的mergeBd存放到bean工厂的mergedBeanDefinitions map结构中。

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

不是抽象类,不是单例,还不是延迟加载的bean,才可以在Spring启动过程中被创建。确认该bean可以被创建后,还要判断该bean是FactoryBean还是普通bean。如果是FactoryBean,那么就走FactoryBean自己的生产逻辑。如果是普通bean,那么就走Spring实例化bean的默认逻辑,不管怎样,都需要走getBean(String name)-->doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)方法。下面我们来看doGetBean方法,由于函数体很长,这里对不重要的try..catch分支进行了删减。

1.getBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 普通bean直接去beanName, FactoryBean取去掉'&'前缀的beanName
    final String beanName = transformedBeanName(name);
    Object bean;    
    // 首先尝试去bean工厂singletonObjects容器中获取bean对象。
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        // 从bean工厂获取bean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    //走else分支说明之前该bean之前还未创建过
    else {
        // Spring无法处理循环依赖对象是prototype类型的问题。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {                
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {                
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        //将beanName标记到baen工厂的alreadyCreated的Set中,保证不会重复创建该bean
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 注解@DependsOn。 A->B->C,则先注册和实例化C,然后是B,最后是A
            // 以本项目为例,当创建class Human的bean时,dependsOn数组中会存放"xiawa",因为Human @DepensOn("xiawa")
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // 确定指定的依赖bean是否已注册为依赖于给定bean或其传递依赖项。
                    if (isDependent(beanName, dep)) {
                        throw new xxx;
                    }
                    // 尝试注册依赖的bd,如果已经创建则直接返回
                    registerDependentBean(dep, beanName);
                    //尝试先将依赖的bean创建出来,如果已经创建则直接从容器中获取
                    getBean(dep);
                }
            }

            // 创建单例对象.
            // 重点方法
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                // 从容器中获取刚刚创建好的bean
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // 原型对象的bean创建
            else if (mbd.isPrototype()) {
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                Object scopedInstance = scope.get(beanName, () -> {
                    beforePrototypeCreation(beanName);
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                });
                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 返回bean前做最后的类型检查和转换
    if (requiredType != null && !requiredType.isInstance(bean)) {
        T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
        return convertedBean;
    }
    return (T) bean;
}

首先通过transformedBeanName(name)进行命名转换,主要针对FactoryBean的名称转换。然后尝试去bean工厂singletonObjects容器中获取已经缓存好的bean实例,拿不到再去走正在的创建流程。

这种以空间换时间的思想在整个Spring框架中展现的淋漓尽致,小到属性,大到bd,乃至bean实例都无一例外的先查缓存,尽量做到一次解析,多次使用。这和Java的“一次编译,处处运行”的理念交相辉映,相得益彰。

能获取到的执行流程非常简单,留给读者自己分析吧。那么现在进入长长的else分支,第一个if块是和循环依赖相关的组件。后续会有专门分析循环依赖的文章,再重点分析,这里暂时先跳过。简单知道Spring无法处理prototype的循环依赖就行了。接下来是一段关于ParentBeanFactory的场景,如果用户没有指定过bean工厂的层级关系,parentBeanFactory值就是null。ParentBeanFactory场景的这块代码并不难度,但是疏于本人从未指定过BeanFactory的层级关系项目,故这里暂时不急于分析,后续如有用到再回来补充。parentBeanFactory=null,相关的if语句块不会进入,流程继续望下走。typeCheckOnly=false是入参,markBeanAsCreated方法会执行。它的主要用途是在bean工厂的alreadyCreated集合中添加beanName,表示beanName已经创建了。

接下来进入try语句块,首先获取当前正在初始化bean的@DepensOn。比如本项目中,Human类依赖Eve类。所以要遍历依赖项,先将依赖的bean率先创建出来才行。嵌套执行的getBean(dep)方法就在说明这个问题。if (mbd.isSingleton()){...}语句块中是本文的主流程,它负责创建singleton的bean对象。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            // 如果当前正在创建的bean还处在另外线程的删除流程中。那就停止创建并抛出异常。
            if (this.singletonsCurrentlyInDestruction) {
                throw new 我都在被销毁了,还创建我干啥?!;
            }
            // 将正在创建的bean加入到Set<String> singletonsCurrentlyInCreation中
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                // 调用传入的lambda方法。实际上就是调用createBean(beanName, mbd, args);
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (Exception ex) {
                throw dosomething();
            }
            finally {
                // 将正在创建的bean从Set<String> singletonsCurrentlyInCreation中移除
                afterSingletonCreation(beanName);
            }
            // <beanName, beanObj>添加到bean工厂的singletonObjects中。
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

核心方法是singletonObject = singletonFactory.getObject();也就是调用传入lambda表达式中的核心方法createBean获得创建好的bean,然后addSingleton

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值