Spring源码--InitializingBean

16 篇文章 0 订阅

使用背景

因为需要支持其他项目组改造任务,需要了解该系统相关框架和部分代码,在查看该系统已开发好的模块时,发现对于配置类,使用了不同的bean初始化方式。
如下:
在这里插入图片描述
在这里插入图片描述
分别使用了spring中的InitializingBean和@Bean的初始化,由于InitializingBean之前没有使用过,所以来学习一下。
附spring中bean实例化过程如下:
在这里插入图片描述

说明

InitializingBean接口只包含一个方法afterPropertiesSet(),凡是继承了InitializingBean接口的类,在初始化时都会调用这方法。
源码及分析:(网络参考)

package org.springframework.beans.factory;

/**
 *  //由bean实现的接口,一旦bean工厂设置了它们的所有属性,就需要对其进行响应:
 *	例如,执行定制初始化,或检查所有强制属性是否已设置。
 * Interface to be implemented by beans that need to react once all their
 * properties have been set by a BeanFactory: for example, to perform custom
 * initialization, or merely to check that all mandatory properties have been set.
 *
 * //实现InitializingBean的另一种方法是指定一个定制的init-方法,例如在XML bean定义中
 * <p>An alternative to implementing InitializingBean is specifying a custom
 * init-method, for example in an XML bean definition.
 * For a list of all bean lifecycle methods, see the
 * {@link BeanFactory BeanFactory javadocs}.
 *
 * @author Rod Johnson
 * @see BeanNameAware
 * @see BeanFactoryAware
 * @see BeanFactory
 * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
 * @see org.springframework.context.ApplicationContextAware
 */
public interface InitializingBean {

	/**
	 *//在BeanFactory设置了提供的所有bean属性后调用,
	 *//此方法允许bean实例仅在设置了所有bean属性之后才能执行初始化,并在配置错误时抛出异常。
	 *//在发生错误配置(如设置基本属性失败)或初始化失败的情况下会抛出Exception 
	 * Invoked by a BeanFactory after it has set all bean properties supplied
	 * (and satisfied BeanFactoryAware and ApplicationContextAware).
	 * <p>This method allows the bean instance to perform initialization only
	 * possible when all bean properties have been set and to throw an
	 * exception in the event of misconfiguration.
	 * @throws Exception in the event of misconfiguration (such
	 * as failure to set an essential property) or if initialization fails.
	 */
	void afterPropertiesSet() throws Exception;

}

通过上述的注释以及方法名可了解到,InitializingBean中的afterPropertiesSet()方法是在属性设置后调用的。

在bean容器启动后才可以对bean进行实例化,Bean容器的最终实现类AbstractAutowireCapableBeanFactory中,包含了如下内容:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //...省略很多代码 下面开始初始化 关键就是两个步骤
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);   //这里执行了注入属性和依赖的操作
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);//这里执行了initMethod 和 afterPropertiesSet
            }
        }
         //...省略很多代码 
        return exposedObject;
    }

主要看到了initializeBean(beanName, exposedObject, mbd);这里执行了initMethod 和 afterPropertiesSet,继续追踪源码,

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    invokeAwareMethods(beanName, bean);

                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            //这里判断是BeanFactoryAware, ServletContextAware之类的aware类型,如果是的话就执行对于的Aware方法
            //把beanFactory啊 servletContext啊之类的依赖set进去
            invokeAwareMethods(beanName, bean);
        }
        
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {   
            //如果实现了BeanPostProcessor接口 这里会执行postProcessBeforeInitialization方法
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        try {
            //这里就开始执行initMethod 和 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()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {
        boolean isInitializingBean = (bean instanceof InitializingBean);//先判断是否实现了InitializingBean接口
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
             //.....省略很多代码            
            else {
                //执行afterPropertiesSet()方法
                ((InitializingBean) bean).afterPropertiesSet(); 
            }
        }
        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                //如果配置了initMethod 就执行initMethod方法 这里只是取到了方法名,显然是要通过反射调用了
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

至此可以看到执行了afterPropertiesSet()方法。

小结

通过上述可以了解:

1.Spring为bean提供了两种初始化bean的方式,分别是实现InitializingBean接口,或者是使用init-method,两种方式可以同时使用。
2.实现InitializingBean接口是直接调用的afterPropertiesSet()方法,init-method是通过反射实现,相比较下,实现接口效率较高,但是对spring有依赖。
3.如果调用afterPropertiesSet()方法时出错,则不调用init-method指定的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值