zoukankan      html  css  js  c++  java
  • Spring中初始化bean和销毁bean的时候执行某个方法的详解

    关于在spring  容器初始化 bean 和销毁前所做的操作定义方式有三种:

     

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

     

     

    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方法

     

     

    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. }  

     

    1. <bean id="dataInitializer" class="com.somnus.demo.DataInitializer" init-method="initMethod" destory-method="destroyMethod"/>  

     

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

    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讲解的非常清楚,源码如下:

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

     

  • 相关阅读:
    1-5概率的公理化的定义
    1-4几何概型
    1-3古典概型
    求逆序对数量
    1-2事件的基本运算
    1001 害死人不偿命的(3n+1)猜想 (15 分)
    北京周末去哪儿 —— 国家博物馆
    北京周末去哪儿 —— 天安门广场
    angular中使用ckplayer播放器
    java MD5/AES/DES加解密汇总
  • 原文地址:https://www.cnblogs.com/xuxiuxiu/p/7081471.html
Copyright © 2011-2022 走看看