Spring源码解析之Bean的初始化过程详解

柔情似水 2024-05-07 ⋅ 39 阅读

在Spring框架中,Bean的初始化过程是非常重要的,它涉及到整个Spring应用程序的运行和配置。本文将深入分析Spring中Bean的初始化过程,从源码角度对其进行详细解析。

Bean的初始化过程

在Spring中,Bean的初始化过程主要包括以下几个步骤:

  1. 实例化Bean对象
  2. 设置Bean对象的属性值
  3. 调用Bean的初始化方法
  4. 返回Bean对象

下面我们将分析每个步骤的源码实现。

实例化Bean对象

首先,Spring会通过反射机制实例化Bean对象,这是通过BeanFactory的getBean方法实现的。具体实现代码如下:

protected Object doGetBean(final String name, final Class<?> requiredType, final Object[] args, boolean typeCheckOnly) 
        throws BeansException {
    final String beanName = transformedBeanName(name);
    Object bean = null;

    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } 
    
    if (bean == null) {
        // 创建Bean实例
        bean = createBeanInstance(beanName, mbd, args);
    }

    return bean;
}

设置Bean对象的属性值

接下来,Spring会通过反射机制为Bean对象设置属性值。具体实现代码如下:

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();
    if (pvs.isEmpty()) {
        return;
    }

    // 对Bean对象进行属性赋值
    bw.setPropertyValues(pvs);
}

调用Bean的初始化方法

在属性值设置完成之后,Spring会调用Bean的初始化方法。初始化方法可以通过@Bean注解的initMethod属性指定,也可以通过实现InitializingBean接口来定义。具体实现代码如下:

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
}

返回Bean对象

最后一步是返回经过实例化、属性值设置和初始化方法调用后的Bean对象。Spring会将Bean对象保存在容器中,以供其他组件使用。具体实现代码如下:

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName,
        @Nullable RootBeanDefinition mbd) {

    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has factory method '" + name + "'");
        }
        return new FactoryBeanReference(beanName, (FactoryBean<?>) beanInstance);
    }
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    Object object = doGetObjectFromFactoryBean((FactoryBean<?>) beanInstance, beanName);
    if (object != beanInstance) {
        validateScope(beanName, (FactoryBean<?>) beanInstance);
    }
    return object;
}

总结

通过以上分析,我们可以看到Spring中Bean的初始化过程是一个复杂的流程。Spring通过反射机制实例化Bean对象,设置属性值并调用初始化方法,最终返回Bean对象。这个过程非常关键,它决定了Spring应用程序的运行和配置。希望本文对您理解Spring中Bean的初始化过程有所帮助。如果您有任何问题或建议,请随时留言,我们将尽快回复。感谢阅读!


全部评论: 0

    我有话说: