zoukankan      html  css  js  c++  java
  • spring中InitializingBean接口使用理解

    转:https://www.cnblogs.com/study-everyday/p/6257127.html

     

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

    测试程序如下:

    复制代码
    1. import org.springframework.beans.factory.InitializingBean;
    2. public class TestInitializingBean implements InitializingBean{
    3. @Override
    4. public void afterPropertiesSet() throws Exception {
    5. System.out.println("ceshi InitializingBean");
    6. }
    7. public void testInit(){
    8. System.out.println("ceshi init-method");
    9. }
    10. }
    复制代码

    配置文件如下:

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

    Main主程序如下:

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

    运行Main程序,打印如下结果:

    1. ceshi InitializingBean

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

    问题

    实现InitializingBean接口与在配置文件中指定init-method有什么不同?

    修改配置文件,加上init-method配置,修改如下:

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

    在配置文件中加入init-method="testInit"。

    运行Main程序,打印如下结果:

    1. ceshi InitializingBean
    2. ceshi init-method

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

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

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

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

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

    总结

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

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

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

  • 相关阅读:
    Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. ......
    UVA 1597 Searching the Web
    UVA 1596 Bug Hunt
    UVA 230 Borrowers
    UVA 221 Urban Elevations
    UVA 814 The Letter Carrier's Rounds
    UVA 207 PGA Tour Prize Money
    UVA 1592 Database
    UVA 540 Team Queue
    UVA 12096 The SetStack Computer
  • 原文地址:https://www.cnblogs.com/SmileWindy/p/9103701.html
Copyright © 2011-2022 走看看