Spring4.3.x 容器中bean的创建过程(4)—— 执行bean的初始化方法

概述

Spring4.3.x 容器中bean的创建过程(1)——走进初始化bean的主要战场一篇中我们找到了初始化bean的主要场所在AbstractAutowireCapableBeanFactory类中的doCreateBean方法中,在这个方法中首先调用createBeanInstance方法创建bean的实例;然后调用populateBean方法设置bean的属性;接着调用initializeBean方法执行Bean后处理器和InitializingBean对象的afterPropertiesSet方法以及init-method方法;最后调用registerDisposableBeanIfNecessary方法注册bean的销毁方法。它的每一步都比较繁琐,所以我把他们分开来探讨。在 Spring4.3.x 容器中bean的创建过程(2)——实例化Bean一篇中,已经探讨了第一步实例化bean。在 Spring4.3.x 容器中bean的创建过程(3)—— 初始化bean的属性值 中探讨了通过BeanWrapper对象设置bean的属性。这一篇则探讨最后一步——执行初始化方法并结束bean的创建。

执行bean的初始化方法

AbstractAutowireCapableBeanFactory类中的doCreateBean方法调用它的initializeBean方法来执行与bean初始化相关的各种初始化方法,initializeBean方法的源码如下。

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        // 首先执行Aware接口的方法
        // 这里涉及的Aware接口有BeanFactoryAware、BeanClassLoaderAware和BeanNameAware
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        } else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行bean后处理器的postProcessBeforeInitialization方法
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            // 执行实现自InitializingBean接口的afterPropertiesSet()方法
            // 执行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后处理器的postProcessAfterInitialization方法
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

如果bean实现了BeanFactoryAware、BeanClassLoaderAware或者BeanNameAware接口,initializeBean方法首先执行这些接口相应的方法,以确保后面的操作能够拿到相应的对象,比如BeanFactory对象。接下来在执行bean的自身的初始化方法之前,则会执行bean后处理器的postProcessBeforeInitialization方法;在执行bean的自身的初始化方法之后,会执行bean后处理器的postProcessAfterInitialization方法。下面我们分别看看这4个方面的源码。

(1)执行Aware接口的方法

initializeBean方法调用AbstractAutowireCapableBeanFactory类的invokeAwareMethods方法完成这向任务,源码如下。

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

在invokeAwareMethods方法中,我们只看到BeanFactoryAware、BeanClassLoaderAware和BeanNameAware三个接口的执行,Spring中还有其他Aware接口(比如ApplicationContextAware、ResourceLoaderAware、EnvironmentAware等)没有得到执行。在Spring中,其他Aware接口在bean后处理器中执行,比如ApplicationContextAware、ResourceLoaderAware和EnvironmentAware会被ApplicationContextAwareProcessor后处理器处理,这个ApplicationContextAwareProcessor会在bean工厂创建后被添加到容器中。

(2)执行bean后处理器的postProcessBeforeInitialization方法

initializeBean方法调用AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInitialization方法来发起post方法的执行,源码如下。

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

在applyBeanPostProcessorsBeforeInitialization方法中,只要post方法返回结果为null,则终止其他bean后处理的执行。在这里我们看看ApplicationContextAwareProcessor后处理器的postProcessBeforeInitialization方法源码,如下。

    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        } else {
            // 执行Aware接口
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    /**执行Aware接口**/
    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }
(3)执行bean的初始化方法

initializeBean方法调用AbstractAutowireCapableBeanFactory类的invokeInitMethods方法来执行bean的初始化方法,源码如下。

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

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                } catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            } else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

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

从invokeInitMethods方法中,首先执行InitializingBean接口的afterPropertiesSet方法,然后调用invokeCustomInitMethod方法执行自定义的初始化方法。下面是invokeCustomInitMethod方法的源码。

    protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
        String initMethodName = mbd.getInitMethodName();
        // 检查是否不在乎初始化方法是否是public的
        final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
                BeanUtils.findMethod(bean.getClass(), initMethodName) :
                ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
        if (initMethod == null) {
            if (mbd.isEnforceInitMethod()) {
                throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
                        initMethodName + "' on bean with name '" + beanName + "'");
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("No default init method named '" + initMethodName +
                            "' found on bean with name '" + beanName + "'");
                }
                // Ignore non-existent default lifecycle methods.
                return;
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
        }

        // 执行初始化操作
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                @Override
                public Object run() throws Exception {
                    ReflectionUtils.makeAccessible(initMethod);
                    return null;
                }
            });
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                    public Object run() throws Exception {
                        initMethod.invoke(bean);
                        return null;
                    }
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                InvocationTargetException ex = (InvocationTargetException) pae.getException();
                throw ex.getTargetException();
            }
        } else {
            try {
                ReflectionUtils.makeAccessible(initMethod);
                initMethod.invoke(bean);
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }

invokeCustomInitMethod方法的作用是,根据方法名称获取自定义的初始化方法,然后执行bean初始化方法。

(4)执行bean后处理器的postProcessAfterInitialization方法

initializeBean方法调用AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsAfterInitialization方法来发起post方法的执行,源码如下。

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

在applyBeanPostProcessorsAfterInitialization方法中,只要post方法返回结果为null,则终止其他bean后处理的执行。

总结

在执行bean完成属性设置后执行初始化方法的过程中,Spring对bean的初始化操作提供了提供了如下扩展点。

(1)Spring提供了各种XxxAware接口,以在初始化的时候向bean注入当前容器拥有的Xxx对象,比如BeanFactoryAware、ApplicationContextAware、ResourceLoaderAware、EnvironmentAware等。

(2)Spring提供了BeanPostProcessor接口,可以在执行bean自身的初始化方法前后执行相应的post方法。

(3)Spring提供了InitializingBean接口,可以在bean中实现这个接口的afterPropertiesSet()方法作为初始化方法。

(4)在xml文件中配置init-method属性或者在java代码中使用@PostConstruct指定初始化方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值