深入理解Spring IOC之扩展篇(三)、InitializingBean、@PostConstruct、SmartInitializingSingleton

简介: 深入理解Spring IOC之扩展篇(三)、InitializingBean、@PostConstruct、SmartInitializingSingleton

本文主要介绍三个初始化的方式,分别是@PostConstruct,InitializingBean,以及SmartInitializingSingleton这三个,我们直接三个一起用,来看看代码哈。


@Component
public class TestP implements InitializingBean, SmartInitializingSingleton {
    @PostConstruct
    public void test() {
        System.out.println("@PostConstruct");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        // InitializingBean 的方法
        System.out.println("afterPropertiesSet");
    }
    @Override
    public void afterSingletonsInstantiated() {
        // SmartInitializingSingleton 的方法
        System.out.println("afterSingletonsInstantiated");
    }
}


代码很简单,我们来看看容器启动后的结果:


1686812056652.png


我们可以看到,三种初始化方式对应的业务逻辑都被执行了,并且我们可以观察到,@PostConstruct是最先被执行的,然后是InitializingBean,最后是SmartInitializingSingleton,那么他们具体的区别是什么呢?我们一起到源码种看看。

调用初始化的代码位于AbstractAutowireCapableBeanFactory中的initializeBean方法中


protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    // 调用几个Aware接口
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
          invokeAwareMethods(beanName, bean);
          return null;
        }
      }, getAccessControlContext());
    }
    else {
      invokeAwareMethods(beanName, bean);
    }
    // 调用所有的BeanPostProcessor的postProcessBeforeInitialization
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
      // 调用InitializingBean的方法和自定义初始化方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }
    // 执行所有BeanPostProcessor的postProcessAfterInitialization方法
    if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
  }


在这个方法中,我们很明显的可以看到,InitializingBean的执行位置,那么@PostConstruct是在哪里执行的呢?经过debug,我们可以发现它是在调用所有的BeanPostProcessor的postProcessBeforeInitialization的时候被执行的(CommonAnnotationBeanPostProcessor中)。然后SmartInitializingSingleton这个东西需要先说一下,Spring4.0的时候是没有这个东西的,这个是4.1之后加入进来的,这个也可以用来做初始化之后的一些操作,那么它又是什么时候被执行的呢?我们可以在DefaultListableBeanFactory中的preInstantiateSingletons中最后几行中发现:


1686812064368.png


而这个时候,所有的Bean都已经被初始化了。所以我们在这里做一个小小的总结:这三个初始化的方法,执行先后顺序是@PostConstruct,然后是InitializingBean,最后是SmartInitializingSingleton。举个使用上的小例子,如果A bean要依赖B bean初始化产生的数据的话,那么就可以让A来实现SmartInitializingSingleton,B来实现InitializingBean或者使用@PostConstruct,InitializingBean和@PostConstruct这两个初始化的方式在绝大多数情况下都没什么差别。另外需要注意的是这三个初始化的方法,都不要和之前的BeanFactoryPostProcessor以及BeanPostProcessor一起用,因为是在容器不同阶段来做的事情,比如我举一个例子:


@Component
public class AProcessor implements BeanPostProcessor, PriorityOrdered {
    @PostConstruct
    public void test() {
        System.out.println("AProcessor @PostConstruct");
    }
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("aa");
        return null;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bb");
        return null;
    }
    @Override
    public int getOrder() {
        return 0;
    }
}


这个类实现了BeanPostProcessor 和PriorityOrdered 这两个接口,然后我们启动之后发现@PostConstruct里面的东西并没有被执行,这个原因是因为这个类初始化的时候用作执行@PostConstruct的BeanPostProcessor 还没有被初始化,所以当然无法执行喽,这只不过是我随随便便就想到的一个,还有可能又其他坑的,所以说尽可能分开用。

写文章不易,尤其完了要对一个庞大的东西做总结更为不易,所以你的赞对我很重要,求点个赞🥺~

目录
相关文章
|
4天前
|
XML Java 数据格式
Spring框架入门:IoC与DI
【5月更文挑战第15天】本文介绍了Spring框架的核心特性——IoC(控制反转)和DI(依赖注入)。IoC通过将对象的创建和依赖关系管理交给容器,实现解耦。DI作为IoC的实现方式,允许外部注入依赖对象。文章讨论了过度依赖容器、配置复杂度等常见问题,并提出通过合理划分配置、使用注解简化管理等解决策略。同时,提醒开发者注意过度依赖注入和循环依赖,建议适度使用构造器注入和避免循环引用。通过代码示例展示了注解实现DI和配置类的使用。掌握IoC和DI能提升应用的灵活性和可维护性,实践中的反思和优化至关重要。
18 4
|
4天前
|
Java 测试技术 开发者
Spring IoC容器通过依赖注入机制实现控制反转
【4月更文挑战第30天】Spring IoC容器通过依赖注入机制实现控制反转
22 0
|
4天前
|
XML Java 程序员
Spring特性之二——IOC控制反转
Spring特性之二——IOC控制反转
16 4
|
4天前
|
安全 Java 开发者
在Spring框架中,IoC和AOP是如何实现的?
【4月更文挑战第30天】在Spring框架中,IoC和AOP是如何实现的?
24 0
|
4天前
|
XML Java 程序员
什么是Spring的IoC容器?
【4月更文挑战第30天】什么是Spring的IoC容器?
20 0
|
4天前
|
Java Spring 容器
【Spring系列笔记】IOC与DI
IoC 和 DI 是面向对象编程中的两个相关概念,它们主要用于解决程序中的依赖管理和解耦问题。 控制反转是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入和依赖查找。
35 2
|
4天前
|
Java 测试技术 数据库连接
Spring中ioc的优点
总之,Spring中的IoC提供了一种更加灵活、可维护、可测试和可扩展的方式来管理组件之间的依赖关系,从而提高了应用程序的质量和可维护性。这使得开发人员能够更专注于业务逻辑而不是底层的技术细节。
32 1
|
4天前
|
Java 应用服务中间件 Spring
|
4天前
|
XML Java 数据格式
Spring IOC的源码解析
【4月更文挑战第17天】Spring IOC(控制反转)的核心功能是通过依赖注入(DI)来管理对象的创建和它们之间的依赖关系。要深入理解Spring IOC的工作原理,我们可以从其源码分析入手,特别是关注如何创建和管理Bean以及依赖注入的实现
22 1
|
4天前
|
XML Java 数据格式
Spring IOC—基于XML配置和管理Bean 万字详解(通俗易懂)
Spring 第二节 IOC—基于XML配置和管理Bean 万字详解!。
97 5