Skip to content

Bean 的依赖注入之 @PostConstruct 和 InitializingBean 接口的调用

TIP

要在 bean 实例化之后,执行某些代码有两种方式。

  1. 在某个方法上面添加 @PostConstruct;
  2. 类实现 InitializingBean 方法;

由下面的源码执行过程可以看出,二者是可以同时存在的,并且执行顺序是 @PostConstruct -> InitializingBean.afterPropertiesSet()

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ ├─下面是依赖注入的核心方法(非常重要)
│ │ │ │ │ │ │ │ ├─populateBean(beanName, mbd, instanceWrapper);
│ │ │ │ │ │ │ │ ├─下面是依赖注入完成后的调用(非常重要)
│ │ │ │ │ │ │ │ ├─exposedObject = initializeBean(beanName, exposedObject, mbd);
│ │ │ │ │ │ │ │ │ ├─先执行 @PostConstruct
│ │ │ │ │ │ │ │ │ ├─wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
│ │ │ │ │ │ │ │ │ ├─再执行实现了 InitializingBean 接口的类的 afterPropertiesSet() 方法
│ │ │ │ │ │ │ │ │ ├─invokeInitMethods(beanName, wrappedBean, mbd);

@PostConstruct 支撑之 InitDestroyAnnotationBeanPostProcessor

支撑了对 @PostConstruct 注解方法的调用。

java
public class InitDestroyAnnotationBeanPostProcessor
        implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            // 完成对加了 @PostConstruct 注解方法的调用
            metadata.invokeInitMethods(bean, beanName);
        } catch (InvocationTargetException ex) {
            throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
        } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
        }
        return bean;
    }
}

InitializingBean.afterPropertiesSet() 的调用

java
protected void invokeInitMethods(String beanName, 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) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}