为了账号安全,请及时绑定邮箱和手机立即绑定

InitializingBean使用

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会自动执行该方法。

package org.springframework.beans.factory;/**
 * 所有由BeanFactory设置的所有属性都需要响应的bean的接口:例如,执行自定义初始化,或者只是检查所有强制属性是否被设置。
 *实现InitializingBean的替代方法是指定一个自定义init方法,例如在XML bean定义中。
 */public interface InitializingBean {    /**
     * 在BeanFactory设置了提供的所有bean属性后,由BeanFactory调用。 
     *这个方法允许bean实例在所有的bean属性被设置时才能执行
     */
    void afterPropertiesSet() throws Exception;

}

在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则先调用afterPropertiesSet方法,再调用init-method中指定的方法。

<bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>

这种方式在spring中是怎么实现的呢?
通过查看spring加载bean的源码类(AbstractAutowireCapableBeanFactory)可以看出玄机
AbstractAutowireCapableBeanFactory类中的invokeInitMethods方法讲解的非常清楚,源码如下:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {        //首先看该bean是否实现了实现了InitializingBean接口,若已实现,则直接调用bean的afterPropertiesSet方法
        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 {                            //直接调用afterPropertiesSet
                            ((InitializingBean) bean).afterPropertiesSet();                            return null;
                        }
                    }, getAccessControlContext());
                }                catch (PrivilegedActionException pae) {                    throw pae.getException();
                }
            }            else {                //直接调用afterPropertiesSet
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();            //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {                //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现的
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

观察源码可得出以下结论
summary:

  1. spring为bean提供了两种初始化bean的方式,实现InitializingBean接口而实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用

  2. 实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法相对来说效率要高。但init-method方式消除了对spring的依赖

  3. 若调用afterPropertiesSet方法时产生异常,则也不会再调用init-method指定的方法





作者:芥末无疆sss
链接:https://www.jianshu.com/p/f08be158baa4
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消