createBean方法详解

前言:

  createBean是创建Bean的主要方法

   该方法位于:AbstractBeanFactory的doGetBean方法中的createBean调用、

createBean方法流程图:

 

 createBean源码解析:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;//该参数是从AbstractBeanFactory的doGetBean传递过来的父子容器合并BeanDefinition

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        //判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            //克隆一份BeanDefinition,用来设置上加载出来的class对象
            //之所以后续用该副本操作,是因为不希望将解析的class绑定到缓存里的BeanDefinition
            //因为class有可能是每次都需要动态解析出来的
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        //校验和准备Bean中的方法覆盖
        try {
            mbdToUse.prepareMethodOverrides();//如果是0个则抛异常,如果是1个也就没有重载的必要
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
            //resolveBeforeInstantiation只是针对有自定义的targetsource,
            //因为自定义的targetsource不是spring的bena,那么肯定不需要进行后续的一系列的实例化,初始化。
            //所以可以在resolveBeforeInstantiation直接进行proxy
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                //如果这里有处理器在bean创建的之前 给出了代理bean,则无需执行后续的逻辑,
                // 直接返回用户给出的bean
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            //创建Bean的入口
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }
createBean源码解析

 

createBean方法大致流程:

  (1)判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载(如果可以,克隆一份BeanDefinition)  

        之所以使用副本进行后续的操作和创建,是不希望去修改到容器缓存里的BeanDefinition

    (2)用BeanDefinition副本调用prepareMethodOverrides()方法,进行校验Bean和准备Bean中的方法覆盖(处理方法覆盖

  (3)⭐处理Bean配置的初始化前后的处理器(前置:该方法里头会调用所有的Bean处理器,如果处理器中有调换了bean的,则返回bean,如果没有则返回null)

  (4)⭐调用doCreateBean()方法,该方法是创建Bean的入口

 

doCreateBean方法流程图:

 

 

 

 

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        //bean实例包装类
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //从未完成创建的包装Bean缓存中清理并获取相关中的包装Bean实例,毕竟是单例,只能存一份
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //创建bean的时候,这里创建bean的实例有三种方法
            //1.工厂方法创建
            //2.构造方法的方式注入
            //3.无参构造方法注入
            instanceWrapper = createBeanInstance(beanName, mbd, args);//********
        }
        //获取被包装的Bean,后续对bean的改动相对于对Wrapper的改动,反之依然
        final Object bean = instanceWrapper.getWrappedInstance();
        //获取实例化对象的类型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        //调用BeanDefinition属性合并完成后的BeanPostProcessor后置处理器
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //@Autowired、@Value标记的属性在这里获取
                    //应用合并后的BeanDefinition后置处理器
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        //向容器中缓存单例模式的Bean对象,以防循环引用
        //判断是否是早期引用的bean,如果是,则允许其提前暴露引用
        // 这里判断的逻辑主要有三个∶
        //1.是否为单例
        //2 是否允许循环引用
        //3.是否是在创建中的bean
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            //这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
            //将还没完全配置好的bean存入到三级缓存中供其他bean使用(暴露引用)
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            //这里的getEarlyBeanReference()方法,并不是在此调用,而是声明好了方法
            //具体的调用在Spring的AbstractBeanFactory的doGetBean的第三行调用
            // DefaultSingletonBeanRegistry类的getSingleton方法中,调用
            // singletonFactory.getObject()(单例工厂的getObject方法返回实例对象)
        }

        // Initialize the bean instance.
        //Bean对象的初始化,依赖注入在此触发
        //这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
        Object exposedObject = bean;//暴露的对象
        try {
            //填充bean实例的属性
            populateBean(beanName, mbd, instanceWrapper);

            //初始化bean,过程如下:
            //1.判断是否实现了BeanNameAware,BeanClassLoaderAware,BeanFactoryAware方法,
            //如果有,则设置相关的属性
            //2.调用bean初始化前的前置(BeanPostProcessor)操作
            //3.执行初始化的方法
            //如果有InitializingBean,则调用afterPropertiesSet
            //如果有InitMethod,则调用初始方法
            //4.调用bean初始化的后置(BeanPostProcessor)操作
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        //若允许循环依赖,则解决相关的循环依赖
        //earlySingletonExposure是前面代码判断出来的是否:暴露引用bean
        if (earlySingletonExposure) {
            //获取指定名称的已注册的单例模式Bean对象
            //这里的getSingleton()从三层缓存中依次去获取,由于
            //先前我们已经将对象存入到三级缓存中,所有这里在三级缓存获取得到
            //然后缓存中的对象被放到了二级缓存中,三级中移除了
            Object earlySingletonReference = getSingleton(beanName, false);//
            if (earlySingletonReference != null) {
                //如果经过initializeBean执行后返回的bean还是同一个(不是代理对象实例,即没有被增强)
                if (exposedObject == bean) {
                    //确保根据名称获取到的
                    exposedObject = earlySingletonReference;
                }
                //如果上面的if没通过,则表明引用的bean和注入的bean不一致,则需要看看依赖于此Bean的先前是否已经
                //allowRawInjectionDespiteWrapping标注是否允许此Bean的原始类型被注入到其他Bean里面,
                //即使自己最终会被包装(代理)
                //dependentBeanMap记录着每个依赖于此Bean的Bean实例集合
                //当发生循环引用时不允许新创建实例对象
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }
                    //因为Bean创建后其所依赖的Bean一定是已经创建的
                    //actualDependentBeans不为空则表示当前Bean创建后其依赖的Bean却没有全部创建完,也就是说
                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName,
                                "Bean with name '" + beanName + "' has been injected into other beans [" +
                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                "] in its raw version as part of a circular reference, but has eventually been " +
                                "wrapped. This means that said other beans do not use the final version of the " +
                                "bean. This is often the result of over-eager type matching - consider using " +
                                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }
doCreateBean源码解析

 

 

doCreateBean方法大致流程:

  (1)判断BeanDefinition是不是单例的,如果是单例的,从未完成创建的包装Bean缓存中清理并获取相关中的包装Bean实例,毕竟是单例,只能存一份

  (2)判断第一步中获到的包装Bean实例如果是空的,调用createBeanInstance()方法创建bean,这里创建bean的实例有三种方法

    (1)尝试获取BeanDefinition里面的Class对象 

    (2)检查是否有权通过反射创建private的Class

    (3)如果bean使用的是java自带的函数式接口Supplier(工厂方法),则调用里头的get创建返回bean实例

    (4)如果BeanDefinition里面有定义Spring的工厂方法如(factory-method),则调用factory-method创建返回实例 

    (5)查询BeanDefinition中有没有缓存好的构造函数或者工厂方法,有则调用创建返回实例

    (6)判断是否使用(带惨构造函数装配)如果都不是最终调用无参构造函数创建返回实例  

  (3)获取被包装的Bean,后续对bean的改动相对于对Wrapper的改动,反之依然,获取实例化对象的类型并放入BeanDefinition中

  (4)对BeanDefinition的后置处理器上锁操作,判断BeanDefinition没有使用后置处理器,后调用applyMergedBeanDefinitionPostProcessors()方法应用合并后的BeanDefinition后置处

    理器(@Autowired、@Value标记的属性在这里获取) applyMergedBeanDefinitionPostProcessors内部跟绝大部分后置处理器一样采用了责任链模式,循环遍历所有后置处理器,

    IF实现了MergedBeanDefinitionPostProcessor接口的 后置处理器便调用postProcessMergedBeanDefinition方法这里我们重点关注:AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()

      (1)进入AutowiredAnnotationBeanPostProcessor类,首先我们可以看到该类的无参构造方法中对@Autowired、@Value注解添加到了该类的成员变量里。

      (2)我们查看postProcessMergedBeanDefinition()方法

        (A)首先第一行调用了findAutowiringMetadata()方法(寻找被注解标记的元数据)

             (1)用类名作为cacheKey(缓存建名) 

             (2)使用cacheKey在缓存容器中查找是否有相关缓存 

             (3)如果缓存容器中没有metadata(元数据)|| metadata的class和给定的clazz不符合则重新获取到构建好的metadata实例并放入到缓存容器中(双重锁机制)

        (B)用前面查找到的metadata调用checkConfigMembers方法,需要Spring用默认策略放到的InjectedElements(注入元素表)   

  (5)判断是否是早期引用的bean,如果是,则允许其提前暴露引用(单例、允许循环引用、创建中的bean)

 

 

 

  doCreateBean简述:

获取赋值BeanWrapper(bean实例包装类)  ---》    调用前面合并好的BeanPostProcess(后置处理器)  ---》   如果是单例模式的bean,缓存进容器中。     ---》 填充Bean实例的属性   ---》初始化Bean实例(初始化前后会调用BeanPostProcessor操作)   --》 IF:(允许暴露引用的bean) 从三层缓存中获取bean,随后解决依赖问题  --》   注册Bean的逻辑销毁   ---》返回Bean实例

posted @ 2021-02-21 16:01  _kerry  阅读(587)  评论(0编辑  收藏  举报