zoukankan      html  css  js  c++  java
  • Spring中的InitializingBean接口的使用

    转载:https://www.cnblogs.com/weiqihome/p/8922937.html

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

    测试,如下:

    复制代码
    import org.springframework.beans.factory.InitializingBean;
    public class TestInitializingBean implements InitializingBean{
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("ceshi InitializingBean");        
        }
        public void testInit(){
            System.out.println("ceshi init-method");        
        }
    }
    复制代码

    配置文件

    <bean id="testInitializingBean" class="com.TestInitializingBean" ></bean>

    Main函数如下

    public class Main {
        public static void main(String[] args){
            ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/java/com/beans.xml");
        }
    }

    测试结果为:

    ceshi InitializingBean

    这说明在spring初始化bean的时候,如果bean实现了InitializingBean接口,会自动调用afterPropertiesSet方法。

    那么问题来了,在配置bean的时候使用init-method配置也可以为bean配置初始化方法,那这两个哪个会先执行呢,接下来测试一下,修改配置文件,加上init-method:

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

    运行程序,得出结果:

    ceshi InitializingBean
    ceshi init-method

    从结果可以看出,在Spring初始化bean的时候,如果该bean实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertieSet()方法,然后再调用init-method中指定的方法。

    那么这种方式在spring中是怎么实现的呢,通过查看Spring加载bean的源码类AbstractAutowiredCapableBeanFactory可以看出其中的奥妙,AbstractAutowiredCapableBeanFactory类中的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指定的方法。

  • 相关阅读:
    Go 语言简介(下)— 特性
    Array.length vs Array.prototype.length
    【转】javascript Object使用Array的方法
    【转】大话程序猿眼里的高并发架构
    【转】The magic behind array length property
    【转】Build Your own Simplified AngularJS in 200 Lines of JavaScript
    【转】在 2016 年做 PHP 开发是一种什么样的体验?(一)
    【转】大话程序猿眼里的高并发
    php通过token验证表单重复提交
    windows 杀进程软件
  • 原文地址:https://www.cnblogs.com/cq-yangzhou/p/11850428.html
Copyright © 2011-2022 走看看