【Spring IOC】【六】容器源码解析- initializeBean剩下的初始化工作

1  前言

我们的bean经过的应该就剩下initializeBean这个方法,这个方法对上一步的populateBean属性填充完,做最后的剩余工作,这个里边的东西相比之前几个那可真是让人看着开心加愉快了,我们来看。

2  源码分析

2.1  方法通读

看一下 initializeBean 方法的源码:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // aware后缀结尾的类大家应该很熟悉吧
            // 若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行 bean 初始化前置操作
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            /*
             * 调用初始化方法:
             * 1. 若 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet 方法
             * 2. 若用户配置了 bean 的 init-method 属性,则调用用户在配置中指定的方法
             */
            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()) {
            // 执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

以上就是 initializeBean 方法的逻辑。该方法做了如下几件事情:

  1. 检测 bean 是否实现了 *Aware 类型接口,若实现,则向 bean 中注入相应的对象
  2. 执行 bean 初始化前置操作
  3. 执行初始化操作
  4. 执行 bean 初始化后置操作

2.2  invokeAwareMethods

根据 bean 所实现的 Aware 的类型,向 bean 中注入不同类型的对象。

private void invokeAwareMethods(String beanName, Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

2.3  invokeInitMethods

做了两件事,1、就是你的bean如果实现了InitializingBean,会调用你的afterPropertiesSet方法做你的东西。 2、执行你bean的init-method方法。

init-method可以配在xml也可以用注解像这样:@Bean(initMethod = "init", destroyMethod = "destroy")

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

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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 {
                // 调用afterPropertiesSet
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null && bean.getClass() != NullBean.class) {
            String initMethodName = mbd.getInitMethodName();
            if (StringUtils.hasLength(initMethodName) &&
                    !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
                // 调用用户自定义的方法
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

3  小结

这个方法还是比较舒服的,不会拖家带口的带出来一堆东西,Spring很多地方都给我们留了扩展,Spring就是给我们管理bean、增强bean的,管理也就是管理bean的生命周期,增强就是在创建的过程中,创建对应的代理对象出来。我们看完IOC 对于bean的几个创建过程中的方法也是有了大概的认识 比如getBean、doGetBean、createBean、doCreateBean、createBeanInstance、populateBean、intializeBean,中间涉及的缓存、代理、依赖解析、属性解析等等,好多细节也是还没太明白,还是要多看,多运用到自己的业务代码中去,哪里有理解不对的还望指正,今天就到这里了。

posted @ 2023-02-18 22:38  酷酷-  阅读(44)  评论(0编辑  收藏  举报