深入理解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 还没有被初始化,所以当然无法执行喽,这只不过是我随随便便就想到的一个,还有可能又其他坑的,所以说尽可能分开用。

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

目录
相关文章
|
22天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
2月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
218 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
13天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
28 0
|
2月前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
128 9
|
1月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
31 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
2月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
40 4
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
67 0
|
2月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
120 3
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
48 0