优秀的编程知识分享平台

网站首页 > 技术文章 正文

「源码角度」分析Spring容器Bean创建过程以及Bean的生命周期

nanyue 2024-09-07 16:44:11 技术文章 8 ℃

继上一篇文章 Spring如何加载IOC容器以及装载Bean源码解读,从源码中我们分析了Spring容器的加载过程,Bean的创建。在本篇文章,我们继续分析Bean的创建过程源码以及Bean的生命周期。根据源码总结出Bean的生命周期流程图如下:

我们继续追踪源码

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    RootBeanDefinition mbdToUse = mbd;
    // 1、确保此时bean类已经被解析,并且在动态解析类不能存储在共享合并bean定义中时克隆bean定义。
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // 2、准备和验证配置的方法注入
    // 注意:这里处理的是replace-method和lookup-method方法注入,而不是@Override注解
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 3、让beanPostprocessor有机会返回一个代理而不是目标bean实例。
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "beanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 4、执行bean创建,并返回bean的实例
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

其中,又发现了第4步,4、执行bean创建,并返回bean的实例doCreateBean(beanName, mbdToUse, args);位于类AbstractAutowireCapableBeanFactory中,该步骤是创建Bean实际方法,其中,我们也能发现Spring中实际做事的都是doXX的方法,我们继续跟踪doCreateBean方法如下:

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

    // ① 实例化bean
    BeanWrapper instanceWrapper = null;
    // 注意factoryBeanInstanceCache是ConcurrentMap,remove方法会返回删除的键值(如果不存在返回null)
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    // 如果factoryBeanInstanceCache没有缓存对应的BeanWrapper,则重新创建bean实例
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // ② 允许MergedBeanDefinitionPostProcessor后处理器修改已合并的bean定义。
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // ③ 提前缓存ObjectFactory以解决bean之间的循环依赖
    // mbd.isSingleton()->是否单例
    // allowCircularReferences->是否允许循环依赖
    // isSingletonCurrentlyInCreation->该bean是否创建中
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    
    // ④ 初始化bean实例 这里大家要与第①步区分开,到这里bean已经完成了实例化,但是还没有完成初始化的操作,例如bean的属性填充
    Object exposedObject = bean;
    try {
        // 填充bean属性
        populateBean(beanName, mbd, instanceWrapper);
        // 初始化bean
        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);
        }
    }

    // ⑤ 循环依赖检查
    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            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);
                    }
                }
                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.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        // ⑥ 根据bean的作用域注册bean
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    // ⑦ 返回bean实例
    return exposedObject;
}

以上为创建Bean步骤,我们分析其中重要的步骤
第1步,实例化方法为:createBeanInstance(beanName, mbd, args),跟踪代码会发现实例化主要有三种方式,1??工厂方法(实例工厂和静态工厂);2??构造函数实例化(无参构造和有参构造);3??通过实例提供者实例化(Spring5新增的实例化策略)

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {

    // 确保此时beanClass已经被解析
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    // beanClass不为空,且beanClass的修饰符为不为public,且不允许访问非公共构造函数和方法,则抛出异常
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }

    // ① Spring5.0新增的实例化策略,如果设置了该策略,将会覆盖构造方法和工厂方法实例化策略
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    // ② 如果有工厂方法的话,则使用工厂方法实例化bean
    if (mbd.getFactoryMethodName() != null)  {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // ③ 当创建一个相同的bean时,使用之间保存的快照
    // 这里可能会有一个疑问,什么时候会创建相同的bean呢?
    // 		③-->① 单例模式: Spring不会缓存该模式的实例,那么对于单例模式的bean,什么时候会用到该实例化策略呢?
    //                 我们知道对于IoC容器除了可以索取bean之外,还能销毁bean,当我们调用xmlBeanFactory.destroyBean(myBeanName,myBeanInstance),
    //				   销毁bean时,容器是不会销毁已经解析的构造函数快照的,如果再次调用xmlBeanFactory.getBean(myBeanName)时,就会使用该策略了.
    // 		③-->② 原型模式: 对于该模式的理解就简单了,IoC容器不会缓存原型模式bean的实例,当我们第二次向容器索取同一个bean时,就会使用该策略了.
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果该bean已经被解析过
    if (resolved) {
        // 使用已经解析过的构造函数实例化
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        // 使用默认无参构造函数实例化
        else {
            return instantiateBean(beanName, mbd);
        }
    }

    // ④ 确定需要使用的构造函数
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // ⑤ 无任何的特殊处理,则使用默认的无参构造函数实例化bean
    return instantiateBean(beanName, mbd);
}

第4步中, populateBean(beanName, mbd, instanceWrapper);属性填充方法,根据装配类型注入,主要有byName注入和byType注入

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // ① 前置判断
    // 如果BeanWrapper对象为null,则说明没有bean的实例
    if (bw == null) {
        // RootBeanDefinition中有属性,但是bean的实例为空,抛出异常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // RootBeanDefinition中没有属性,直接返回
            return;
        }
    }
    // ② 应用InstantiationAwareBeanPostProcessor处理器
    // 在设置属性之前,给InstantiationAwareBeanPostProcessor一个修改bean状态的机会
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 是否继续填充bean属性
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }

    // ③ 如果InstantiationAwareBeanPostProcessor停止了对bean属性的填充,则直接返回
    if (!continueWithPropertyPopulation) {
        return;
    }

    // 获取PropertyValues属性
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // ④ 解析自动装配类型
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||	mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // byName注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // byType注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }

    // ⑤ 判断是否有InstantiationAwareBeanPostProcessors处理器,并进行处理
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }

    // ⑥ 依赖检查
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // ⑦ 应用属性
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

接下来继续看第4步中初始化bean方法,exposedObject = initializeBean(beanName, exposedObject, mbd);完成有关bean的生命周期的调用AwareMethods、应用bean前置处理器、调用bean的init_method初始化方法、应用bean后置处理器,该方法相当重要啊~

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    // 1、调用各种AwareMethods
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    // 2、应用bean前置处理器
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    // 3、调用bean的init_method初始化方法
    try {
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName,"Invocation of init method failed", ex);
    }
    // 4、应用bean后置处理器
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

至此,Spring容器中自定义单例Bean创建完成并返回。其实,在创建的过程中,还有很多重点问题,比如:如何根据FactoryBean创建Bean,如何根据构造函数创建Bean,特别是Spring是如何解决Bean循环依赖的问题等等,在以后的文章我们会继续分享。

不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我

最近发表
标签列表