主要流程

到这里,bean生命周期已经完成了两件大事:

  1. 调用 createBeanInstance() 方法:完成 bean 的实例化工作
  2. 调用 populateBean() 方法:完成 bean 的属性填充注入工作

接下来是第三件大事:
初始化 Bean,主要工作:调用工厂回调、init方法执行、后置处理器的执行。

  1. protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  2. if (System.getSecurityManager() != null) {
  3. // 安全机制特权处理
  4. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  5. invokeAwareMethods(beanName, bean);
  6. return null;
  7. }, getAccessControlContext());
  8. } else {
  9. // 对特殊的 bean 处理:Aware、 BeanClassLoaderaware、 BeanFactoryAware
  10. invokeAwareMethods(beanName, bean);
  11. }
  12. // 执行前置处理器
  13. Object wrappedBean = bean;
  14. if (mbd == null || !mbd.isSynthetic()) {
  15. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  16. }
  17. // 执行自定义init方法
  18. try {
  19. invokeInitMethods(beanName, wrappedBean, mbd);
  20. } catch (Throwable ex) {
  21. throw new BeanCreationException(
  22. (mbd != null ? mbd.getResourceDescription() : null),
  23. beanName, "Invocation of init method failed", ex);
  24. }
  25. // 执行后置处理器
  26. if (mbd == null || !mbd.isSynthetic()) {
  27. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  28. }
  29. return wrappedBean;
  30. }

流程1 - invokeAwareMethods�

实现 Aware 接口用于让 bean 能拥有某些额外的扩展能力。

  • 如果 bean 实现了 BeanNameAware 接口,则将 beanName 设置进去
  • 如果 bean 实现了 BeanClassLoaderAware 接口,则将 ClassLoader 设置进去
  • 如果 bean 实现了 BeanFactoryAware 接口,则将 beanFactory 设置进去

也就是说实现了上面的接口,就能得到相关的资源。代码如下所示:

  1. private void invokeAwareMethods(String beanName, Object bean) {
  2. if (bean instanceof Aware) {
  3. if (bean instanceof BeanNameAware) {
  4. ((BeanNameAware) bean).setBeanName(beanName);
  5. }
  6. if (bean instanceof BeanClassLoaderAware) {
  7. ClassLoader bcl = getBeanClassLoader();
  8. if (bcl != null) {
  9. ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
  10. }
  11. }
  12. if (bean instanceof BeanFactoryAware) {
  13. ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
  14. }
  15. }
  16. }

流程2 - applyBeanPostProcessorsBeforeInitialization

  1. public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  2. throws BeansException {
  3. Object result = existingBean;
  4. for (BeanPostProcessor processor : getBeanPostProcessors()) {
  5. Object current = processor.postProcessBeforeInitialization(result, beanName);
  6. if (current == null) {
  7. return result;
  8. }
  9. result = current;
  10. }
  11. return result;
  12. }

postProcessBeforeInitialization() 方法是 BeanPostProcessor 接口提供的方法。
image.png
它是在 bean 初始化之前调用的,这时的 bean 已完成了实例化和属性填充注入工作。

🔥 流程3 - invokeInitMethods�

执行自定义init方法。自定义方法的方式:

  1. bean 在 xml 文件中配置 init-method ;
  2. 标签或使用注解 @Bean(initMethod=” “) ;
  3. 实现 InitializingBean 接口,并且在 afterPropertiesSet() 方法中实现自己初始化的业务逻辑。

    1. protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
    2. throws Throwable {
    3. boolean isInitializingBean = (bean instanceof InitializingBean);
    4. if (isInitializingBean && (mbd == null
    5. || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    6. if (logger.isTraceEnabled()) {
    7. logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    8. }
    9. if (System.getSecurityManager() != null) {
    10. try {
    11. AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
    12. ((InitializingBean) bean).afterPropertiesSet();
    13. return null;
    14. }, getAccessControlContext());
    15. } catch (PrivilegedActionException pae) {
    16. throw pae.getException();
    17. }
    18. } else {
    19. ((InitializingBean) bean).afterPropertiesSet();
    20. }
    21. }
    22. if (mbd != null && bean.getClass() != NullBean.class) {
    23. String initMethodName = mbd.getInitMethodName();
    24. if (StringUtils.hasLength(initMethodName) &&
    25. !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
    26. !mbd.isExternallyManagedInitMethod(initMethodName)) {
    27. invokeCustomInitMethod(beanName, bean, mbd);
    28. }
    29. }
    30. }

    流程4 - applyBeanPostProcessorsAfterInitialization�

    postProcessAfterInitialization() 方法是 BeanPostProcessor 接口提供的方法,可以看到它是在 bean 初始化之后调用的,这时的 bean 已完成了实例化,属性填充注入,初始化的工作;可以认为是一个完整的 bean 已在 spring 容器中。
    如果使用了 spring aop 功能,那么代理对象的产生就在这个 applyBeanPostProcessorsAfterInitialization() 方法中。

    Spring 初始化 bean 的方式小结

  • xml 配置文件中指定 init-method 标签
  • 使用 @PostConstruct 注解
  • 实现 InitializingBean 接口
  • 使用 @Bean(initMethod=” “) 注解指定