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指定的方法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云霄雨霁

设计模式----适配器模式

1290
来自专栏封碎

Android获取应用程序的大小 博客分类: Android AndroidOSF#Security

       今天碰到个问题,想获取某个已安装的包的大小,没找到合适的方法。搜索了一下,发现PackageManager里面有个getPackageSizeIn...

1372
来自专栏yl 成长笔记

策略模式及其与简单工厂模式的区别

The strategy pattern(also known as the policy pattern) is a behavioural software...

2543
来自专栏移动端开发

Android学习--持久化(二) SharedPreferences

SharedPreferences 也是通过一个简单的Demo来理解SharedPreferences我们该怎么用,说说自己站在一个iOS开发的角度来看这个Sh...

1947
来自专栏编舟记

Java内部类的异常处理

最近遇到一个问题,使用Java写某个DSL标记语言X的parser(解析器)Maven插件的时候,对外暴露一个名为Callback的接口和一个待实现的方法get...

762
来自专栏企鹅号快讯

来仿一仿retrofit

为什么要重复造轮子 在开发领域有一句很流行的话就是不要重复造轮子,因为我们在开发中用到的很多东西早已有很多人去实现了,而且这些实现都是经过时间和开发者检验过的,...

1899
来自专栏JavaEdge

@ConditionalOnMissingBean注解使用

4076
来自专栏Android先生

[译]Android防止内存泄漏的八种方法(下)

在上一篇Android内存泄漏的八种可能(上)中,我们讨论了八种容易发生内存泄漏的代码。其中,尤其严重的是泄漏Activity对象,因为它占用了大量系统内存。不...

872
来自专栏mini188

学习AOP之认识一下Spring AOP

要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口。 在几次面试中都被问及AOP,但是真的没有答上来,或...

690
来自专栏竹清助手

谈谈模板方法设计模式的使用

在项目中经常会遇到一个类的某些方法和另一个类的某些方法功能是相同的,只有部分方法是不同的。这个时候就可以使用模板方法来操作了。其实这种情况很常见:比如我们项目里...

1434

扫码关注云+社区

领取腾讯云代金券