• Spring中初始化bean和销毁bean的时候执行某个方法的详解



    http://blog.csdn.net/ilovesmj/article/details/51261033



    第一种:通过注解@PostConstruct 和 @PreDestroy 方法 实现初始化和销毁bean之前进行的操作


    [java] view plain copy
    1. import javax.annotation.PostConstruct;    
    2. import javax.annotation.PreDestroy;    
    3.   
    4. public class DataInitializer{     
    5.     @PostConstruct  
    6.     public void initMethod() throws Exception {  
    7.         System.out.println("initMethod 被执行");  
    8.     }  
    9.     @PreDestroy  
    10.     public void destroyMethod() throws Exception {  
    11.         System.out.println("destroyMethod 被执行");  
    12.     }  
    13. }  

    第二种是:通过 在xml中定义init-method 和  destory-method方法

    [java] view plain copy
    1. public class DataInitializer{  
    2.     public void initMethod() throws Exception {  
    3.         System.out.println("initMethod 被执行");  
    4.     }  
    5.     public void destroyMethod() throws Exception {  
    6.         System.out.println("destroyMethod 被执行");  
    7.     }  
    8. }  

    [html] view plain copy
    1. <bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>  

    第三种是: 通过bean实现InitializingBean和 DisposableBean接口

    [java] view plain copy
    1. import org.springframework.beans.factory.DisposableBean;  
    2.   
    3. public class DataInitializer implements InitializingBean,DisposableBean{  
    4.       
    5.     @Override  
    6.     public void afterPropertiesSet() throws Exception {  
    7.         System.out.println("afterPropertiesSet 被执行");  
    8.     }  
    9.       
    10.     @Override  
    11.     public void destroy() throws Exception {  
    12.         System.out.println("destroy 被执行");  
    13.     }  
    14.   
    15. }  

    其中第一种和第二种是同一种形式,只不过一种xml配置,另外一种采用注解形式罢了,


    有很大区别的是第三种,

    如果同一个bean同时采用两种方式初始化的时候执行某个方法,首先在执行顺序上就会体现出来。

    先执行afterPropertiesSet(),

    后执行initMethod()


    这里我们看下源码

    这方式在spring中是怎么实现的?

    通过查看spring的加载bean的源码类(AbstractAutowireCapableBeanFactory)可看出其中奥妙

    AbstractAutowireCapableBeanFactory类中的invokeInitMethods讲解的非常清楚,源码如下:

    [java] view plain copy
    1. protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)  
    2.       throws Throwable {  
    3.   //判断该bean是否实现了实现了InitializingBean接口,如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法  
    4.   boolean isInitializingBean = (bean instanceof InitializingBean);  
    5.   if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  
    6.       if (logger.isDebugEnabled()) {  
    7.           logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");  
    8.       }  
    9.         
    10.       if (System.getSecurityManager() != null) {  
    11.           try {  
    12.               AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
    13.                   public Object run() throws Exception {  
    14.                       //直接调用afterPropertiesSet  
    15.                       ((InitializingBean) bean).afterPropertiesSet();  
    16.                       return null;  
    17.                   }  
    18.               },getAccessControlContext());  
    19.           } catch (PrivilegedActionException pae) {  
    20.               throw pae.getException();  
    21.           }  
    22.       }                  
    23.       else {  
    24.           //直接调用afterPropertiesSet  
    25.           ((InitializingBean) bean).afterPropertiesSet();  
    26.       }  
    27.   }  
    28.   if (mbd != null) {  
    29.       String initMethodName = mbd.getInitMethodName();  
    30.       //判断是否指定了init-method方法,如果指定了init-method方法,则再调用制定的init-method  
    31.       if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  
    32.               !mbd.isExternallyManagedInitMethod(initMethodName)) {  
    33.               //进一步查看该方法的源码,可以发现init-method方法中指定的方法是通过反射实现  
    34.           invokeCustomInitMethod(beanName, bean, mbd);  
    35.       }  
    36.   }  

    总结:

    1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过

    init-method指定,两种方式可以同时使用


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

    init-method方式消除了对spring的依赖


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


  • 相关阅读:
    tensorflow学习笔记----TensorBoard讲解
    tensorflow学习笔记----tensorflow在windows的安装及TensorBoard中mnist样例
    vmware workstation环境下虚拟机固定ip的设置
    一致性协议之Paxos算法
    一致性协议之二阶段提交和三阶段提交
    红黑树
    kibana增加验证
    Linux安装nodejs和npm
    Gnu pgp加密解密
    linux记录每次登陆的历史命令
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106675.html
Copyright © 2020-2023  润新知