Spring源码分析-bean的初始化过程

Posted 淡蓝色光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码分析-bean的初始化过程相关的知识,希望对你有一定的参考价值。

初始化过程

  1. 构造 bean
  2. 依赖注入(接下来才是初始化过程)
  3. 获取容器中所有的 BeanPostProcessor,执行其 postProcessBeforeInitialization 方法(@PostConstruct注解指定的初始化方法,就是在这一步由 CommonAnnotationBeanPostProcessor 实现)
  4. 如果 bean 实现了 InitializingBean 接口,执行 afterPropertiesSet 方法
  5. 如果 @Bean 注解中指定了 initMethod 属性,执行指定的方法
  6. 获取容器中所有的 BeanPostProcessor,执行其 postProcessAfterInitialization 方法

源码分析

  • BeanFactory 的 initializeBean 方法中
/**
 * 获取 BeanPostProcessor,执行 postProcessBeforeInitialization 方法
 */
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
/**
 * 执行 bean 指定的初始化方法:InitializingBean 接口的 afterPropertiesSet 方法,@Bean 注解指定的初始化方法
 */
try {
    invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
    throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
}
/**
 * 获取 BeanPostProcessor,执行 postProcessAfterInitialization 方法
 */
if (mbd == null || !mbd.isSynthetic()) {
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
  • invokeInitMethods 方法
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.isTraceEnabled()) {
            logger.trace("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 接口的 afterPropertiesSet 方法
             */
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            /**
             * 执行 @Bean 注解的 initMethod 属性指定的方法
             */
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

以上是关于Spring源码分析-bean的初始化过程的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码分析

09Spring源码-分析篇-DI源码分析

spring源码分析——bean的实例化流程

spring源码分析 销毁方法,初始化之前的方法加载和执行过程分析

spring源码分析IOC容器初始化

spring源码分析IOC容器初始化