您的位置:首页 > 教育 > 锐评 > 探索InitializingBean:Spring框架中的隐藏宝藏

探索InitializingBean:Spring框架中的隐藏宝藏

2024/10/7 2:26:05 来源:https://blog.csdn.net/danci_/article/details/140253358  浏览:    关键词:探索InitializingBean:Spring框架中的隐藏宝藏

​🌈 个人主页:danci_
🔥 系列专栏:《设计模式》《MYSQL》
💪🏻 制定明确可量化的目标,坚持默默的做事。


✨欢迎加入探索MYSQL索引数据结构之旅✨

    👋 Spring框架的浩瀚海洋中,InitializingBean如同一颗闪闪发光的珍珠,等待被你发现。这一隐藏的宝藏,能够让你的Spring应用在初始化时更灵活、可控。本篇文章将带你深入探索InitializingBean的奥秘,揭示其在Spring生命周期中的重要作用,让你的开发之路更加顺畅高效。准备好开启这段奇妙的探索之旅了吗?让我们一起揭开InitializingBean的神秘面纱吧!


目录

一、环境

二、示例

2.1、说明

三、执行过程

3.1 源码解析


一、环境

  • jdk: 1.8
  • spring-boot: 2.7.1

二、示例

@Component
public class TestInit implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("调用TestInit.afterPropertiesSet方法");}
}

运行结果:

2.1、说明

  • springboot提供InitializingBean接口,用户可以实现之来自定义初始化操作
  • 实现InitializingBean接口重写afterPropertiesSet方法并注册到spring容器中,创建实例后即可触发执行自定义初始化操作

三、执行过程

       一直很好奇和想弄清楚什么时候调扩展点afterPropertiesSet()方法呢?用什么方式调用?

为满足好奇,启动一个简单springboot项目跟踪源码执行过程如下:

   

3.1 源码解析

1. Springboot项目启动入口SpringApplication.run

public ConfigurableApplicationContext run(String... args) {// 记录启动开始时间long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = createBootstrapContext();// 准备ApplicationContextConfigurableApplicationContext context = null;configureHeadlessProperty();// 从spring.factories 中获取监听器SpringApplicationRunListeners listeners = getRunListeners(args);// 发布事件listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 环境参数ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置设置进系统参数configureIgnoreBeanInfo(environment);// 输出bannerBanner printedBanner = printBanner(environment);// 创建applicationContext IOC容器context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);// 准备上下文IOC容器,设置了一系列的属性值prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 308行,启动spring容器refreshContext(context);// 刷新后的处理afterRefresh(context, applicationArguments);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}// 发布事件listeners.started(context, timeTakenToStartup);// 调用 runner,实现了 ApplicationRunner或CommandLineRunner 的接口callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}

这里关注调refreshContext(context)来启动容器

 2. SpringApplication.refreshContext启动容器

protected void refresh(ConfigurableApplicationContext applicationContext) {// 734行applicationContext.refresh();}

然后调AbstractApplicationContext.refresh()来启动Spring容器

3. AbstractApplicationContext.refresh()启动Spring容器

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// 启动容器前准备。启动时间、状态和环境等prepareRefresh();// 告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备在上下文中使用bean工厂prepareBeanFactory(beanFactory);try {// 允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 调用在上下文中注册为bean的工厂处理器invokeBeanFactoryPostProcessors(beanFactory);// 注册拦截bean创建的bean处理器。registerBeanPostProcessors(beanFactory);beanPostProcess.end();// 为此上下文初始化消息源。initMessageSource();// 初始化事件广播器initApplicationEventMulticaster();// 初始化特定上下文子类中的其他特殊bean。onRefresh();// 注册事件监听器registerListeners();// 583行,实例化所有剩余的(非lazy-init)单例finishBeanFactoryInitialization(beanFactory);// 完成启动操作finishRefresh();}catch (BeansException ex) {...}finally {resetCommonCaches();contextRefresh.end();}}
}

列出了Spring容器启动的整个过程。本例关注InitializingBean扩展点,其它内容不详细解读。 实例化所有剩余的(非lazy-init)单例 finishBeanFactoryInitialization(beanFactory);

4. AbstractApplicationContext.finishBeanFactoryInitialization(...)初始化(非lazy-init)单例

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {...// 918行,实例化所有剩余的(非lazy-init)单例。beanFactory.preInstantiateSingletons();
}

调bean工厂类的preInstantiateSingletons方法来实例化bean

5. ConfigurableListableBeanFactory.preInstantiateSingletons()实例化bean

@Override
public void preInstantiateSingletons() throws BeansException {...// 955行,获取beangetBean(beanName);...
}

这里由调父父类AbstractBeanFactory.getBean来获取bean

6.AbstractBeanFactory.getBean(beanName)获取bean

public Object getBean(String name) throws BeansException {// 208行return doGetBean(name, null, null, false);
}

然后调本类doGetBean(...)方法获取bean

7. AbstractBeanFactory.doGetBean获取bean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {...// 332行,创建bean实例if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {...}});...}...}return adaptBeanInstance(name, beanInstance, requiredType);
}

然后调子类的createBean来创建实例

8.AbstractAutowireCapableBeanFactory.createBean(...)创建实例

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {...// 542行doCreateBean(beanName, mbdToUse, args);...
}

调本类doCreateBean

9.AbstractAutowireCapableBeanFactory.doCreateBean(...)执行创建bean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {...// 实例化 Bean// 解决循环依赖问题, 是否允许循环依赖 等...// 属性装配, 即自动注入populateBean(beanName, mbd, instanceWrapper);// 620行,应用工厂回调以及初始化方法和bean后处理程序。// 例如init-method、InitializingBean 接口、BeanPostProcessor 接口exposedObject = initializeBean(beanName, exposedObject, mbd);...
}

10. AbstractAutowireCapableBeanFactory.initializeBean处理初始化完成处理

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {...// 方法回调invokeInitMethods(beanName, wrappedBean, mbd);...
}

11. AbstractAutowireCapableBeanFactory.invokeInitMethods实例的方法回调处理

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {boolean isInitializingBean = (bean instanceof InitializingBean);// 判断为InitializingBean的实现类,且重写afterPropertiesSet方法,则调afterPropertiesSet方法if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {...((InitializingBean) bean).afterPropertiesSet();...}...
}

到此,探索InitializingBean已完。

ps: 以上是研读源码加上翻阅许多文献理解的总结,如有错误或不足的地方,欢迎指出,欢迎留言交流。我会继续努力学习和分享更多有干货的内容。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com