• 【spring】InitializingBean接口


      apollo 源码中有这么一个类

      

    public class ReleaseMessageScanner implements InitializingBean
    @Override
    public void afterPropertiesSet() throws Exception {
    //启动线程,定时检查几个侦听器的数据 }
    InitializingBean这个接口中只有一个afterPropertiesSet方法,
    在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。

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

    AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:
    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
        //判断该bean是否实现了实现了InitializingBean接口,如果实现了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>() {
                        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);
            }
        }
    }

    总结

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

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

    3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法

  • 相关阅读:
    pip install报错:RuntimeError: Python version >= 3.5 required
    简明conda使用指南
    Ninja使用Visual Studio(cl.exe)构建
    cmake设定boost python3
    系统程序员成长计划——像机器一样思考(二)
    在Redis Sentinel环境下,jedis该如何配置
    如何用Go语言实现汉诺塔算法
    pt-online-schema-change的实现原理
    MySQL Sniffer
    如何利用docker快速构建MySQL主从复制环境
  • 原文地址:https://www.cnblogs.com/lodor/p/7481436.html
Copyright © 2020-2023  润新知