关于Spring IoC 源码有一处的疑问

Richard_Yi
  • 2.1k

采纳了@代码宇宙 大大的答案。我自己具体的思考在我的答案里有给出。

Spring IoC 在创建对象的时候,可以大致分为3步:

  • createBeanInstance() 实例化
  • populateBean() 属性装配
  • initializeBean() 处理Bean初始化之后的各种回调事件

在阅读AbstractAutowireCapableBeanFactory#initializeBean() 源码的时候,

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            // 涉及到的回调接口点进去一目了然,代码都是自解释的
            // BeanNameAware、BeanClassLoaderAware或BeanFactoryAware
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessBeforeInitialization 回调
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // init-methods
            // 或者是实现了InitializingBean接口,会调用afterPropertiesSet() 方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // BeanPostProcessor 的 postProcessAfterInitialization 回调
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

上面是我自己完成这部分源码阅读学习后的注释版本代码,大家发现没有,BeanPostProcessor 的两个回调都发生在这边,只不过中间处理了 init-method。

这和我原来的认知有点不一样了?因为Spring的源码中代码的命名很多时候是自解释的,很多时候我看英文就知道这些方法的意图,但在这里,为什么BeanPostProcessor的前置处理方法postProcessBeforeInitialization()也是在属性设置完成后调用的?

准确来说到这里已经是after initialization了,难道initialization代表的意思是调用init-method?这样好像能说的通。

这个问题可能会被感觉有点钻牛角尖,但还想听听大家的见解。

回复
阅读 380
2 个回答

命名问题?
init指的是invokeInitMethods

刚刚google到一篇,就想猜想的那样,BeanPostProcessor的意图就是在初始化方法的前后做定制化操作。
现在仔细想想好像这个命名也没毛病。如果真的是在SpringBean实例化之前调用应该叫BeforeInstantiation。源码中的initialization指的就是invokeInitMethods操作.
clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏