当前位置: 首页 > news >正文

Spring源码二十:Bean实例化流程三

上一篇Spring源码十九:Bean实例化流程二中,我们主要讨论了单例Bean创建对象的主要方法getSingleton了解到了他的核心流程无非是:通过一个简单工厂的getObject方法来实例化bean,当然spring在实例化前后提供了扩展如:beforeSingletonCreation与afterSingletonCreate,同样为了提供性能会将实例化后的单例bean放入缓存中;又因为spring设计之初存在三级缓存,所以在放入缓存的时候又会将其他两次的缓存清除。

简单的回忆了之前的内容,我们发现还有一个很重要的点我们没有说到那就是怎么通过简单工厂来创建实例对象的,这一篇咱们详细讨论一下:


createBean

	/*** Central method of this class: creates a bean instance, 创建bean实例对象* populates the bean instance, applies post-processors, etc. 填充bean实例、应用后置处理器* @see #doCreateBean*/@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.// 判断需要创建的bean是否可以实例化、是否可以通过当前类加载器加载Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.// 准备bean中的方法覆盖try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 给BeanPostProcessors一个返回代理而不是目标bean实例的机会。Object bean = resolveBeforeInstantiation(beanName, mbdToUse);// 如果bean配置类后置处理器PostProcessor,则这里返回一个proxy代理对象if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// bean实例对象创建方法Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

因为lockup-method属性与repliace-methon配置属性,现在基本上没有使用场景,而resolveBeanClass与preprareMethodOverrides是为了是实现这个两个方法而生的,所以我们直接来看 resolveBeforeInstantiation方法。

resolveBeforeInstantiation

@Nullableprotected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {// BeanPostProcessor前置处理方法bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {// BeanPostProcessor后置处理方法bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}

InstantiationAwareBeanPostProcessorBeanPostProcessor 的一个子接口,提供了以下方法,用于在 Bean 实例化的不同阶段进行干预:

  • postProcessBeforeInstantiation(Class<?> beanClass, String beanName): 在 Bean 实例化之前调用。
  • postProcessAfterInstantiation(Object bean, String beanName): 在 Bean 实例化之后调用。
  • postProcessProperties(PropertyValues pvs, Object bean, String beanName): 在 Bean 的属性设置之前调用。

这些方法提供了在 Bean 实例化过程中进行自定义逻辑处理的机会,可以用于 Bean 的替换、属性的预处理等操作。

示例代码:

public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {if ("myBean".equals(beanName)) {System.out.println("Before instantiation of " + beanName);// 可以返回一个代理对象或自定义的 Bean 实例}return null; // 返回 null 表示继续默认的实例化过程}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) {System.out.println("After instantiation of " + beanName);return true; // 返回 true 表示继续进行属性设置}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {System.out.println("Processing properties for " + beanName);return pvs; // 可以修改属性值}
}

InstantiationAwareBeanPostProcessor 扩展了 BeanPostProcessor 的功能,提供了在 Bean 实例化的不同阶段进行干预的能力。通过实现 InstantiationAwareBeanPostProcessor 接口,开发人员可以在 Bean 实例化过程中插入自定义逻辑,实现更灵活的 Bean 管理和控制。

实例化与初始化

为了更好地理解 BeanPostProcessorInstantiationAwareBeanPostProcessor 的区别,我们需要明确实例化和初始化的概念。

  • 实例化:实例化是从零到一创建一个 Bean 的过程,即通过调用构造函数生成 Bean 的实例。
  • 初始化:初始化是在 Bean 实例化之后进行的配置过程,包括属性注入、调用初始化方法等。

在 Spring 容器中,Bean 的生命周期大致分为以下几个阶段:

  1. 实例化:通过调用构造函数创建 Bean 实例。
  2. 属性注入:将依赖的属性注入到 Bean 中。
  3. 初始化:调用自定义的初始化方法,进行额外的配置。

BeanPostProcessor 与 InstantiationAwareBeanPostProcessor 的区别

  • 作用阶段

    • BeanPostProcessor 主要作用于初始化阶段,即在 Bean 的属性已经注入之后进行处理。
    • InstantiationAwareBeanPostProcessor 作用于实例化阶段和属性注入阶段,允许在 Bean 实例化之前、之后以及属性注入之前进行处理。
  • 用途

    • BeanPostProcessor 常用于在 Bean 初始化之前和之后执行一些通用的处理逻辑,如代理增强、配置验证等。
    • InstantiationAwareBeanPostProcessor 常用于在 Bean 实例化过程中执行一些特殊的处理逻辑,如提前终止 Bean 创建、动态生成代理对象、修改属性注入逻辑等。

这个方法是在 Bean 初始化后应用所有注册的 BeanPostProcessorpostProcessAfterInitialization 方法,其设计和实现反映了 Spring 框架中依赖注入和面向切面编程的核心理念。

Spring Bean 生命周期管理

在 Spring 框架中,Bean 的生命周期经历了多个阶段,包括实例化、依赖注入、初始化和销毁等。applyBeanPostProcessorsAfterInitialization 方法所处的阶段是在 Bean 初始化之后,即在所有属性被设置后,执行自定义的后处理逻辑。

BeanPostProcessor 接口作用

BeanPostProcessor 接口定义了在 Bean 初始化前后可以插入自定义逻辑的能力。Spring 容器在创建 Bean 的过程中,会检查是否注册了 BeanPostProcessor,如果有,则会在相应的阶段调用其方法。其中,postProcessAfterInitialization 方法是在 Bean 初始化完成后被调用的,允许开发者对 Bean 进行额外的处理或修改。

applyBeanPostProcessorsAfterInitialization 方法分析

  1. 初始化结果对象:方法开始时,首先将 result 对象初始化为 existingBean,即当前的 Bean 实例。这个 existingBean 是在容器中已经完成初始化的对象。

  2. 遍历处理器列表:方法接着遍历所有注册的 BeanPostProcessor,对每一个后处理器调用其 postProcessAfterInitialization 方法。

    • 每个处理器可以在方法内部执行任何与 Bean 相关的操作,例如添加代理、执行验证、修改属性等。
    • 如果某个处理器返回 null,则表示不需要进一步处理,直接返回当前的 result 对象。
  3. 返回处理后的结果:最终返回经过所有后处理器处理后的 result 对象。这个对象可能是原始的 existingBean,也可能是经过多个处理器处理后的新对象。

技术原理分析

  • 面向切面编程(AOP)的应用:通过 BeanPostProcessor 接口,Spring 实现了 AOP 的一种简单形式。开发者可以在 Bean 初始化后插入切面逻辑,例如添加事务、日志等。

  • 依赖注入的增强:允许在 Bean 初始化后对依赖关系进行增强或修改,以适应不同的运行时需求。

  • 灵活性与可扩展性:applyBeanPostProcessorsAfterInitialization 方法展示了 Spring 框架在管理 Bean 生命周期时的高度灵活性和可扩展性。开发者可以通过注册自定义的 BeanPostProcessor 实现特定的业务逻辑,而不必修改现有的 Bean 实现代码。

applyBeanPostProcessorsAfterInitialization 方法在 Spring 框架中扮演了重要角色,通过它,开发者可以在 Bean 初始化完成后添加自定义逻辑,扩展和定制应用程序的行为。理解这个方法的工作原理和技术实现,有助于深入理解 Spring 容器的工作机制,提升对 Bean 生命周期管理的控制和应用开发的灵活性。

总结

http://www.lryc.cn/news/397002.html

相关文章:

  • 前端导出文件时,后端代码出错如何将错误信息返回给前端展示
  • 解决Spring Boot应用中的内存优化问题
  • shark云原生-日志体系-filebeat高级配置(适用于生产)-更新中
  • 响应式设计的双璧:WebKit 支持 CSS Flexbox 和 Grid 布局深度解析
  • Linux软件包管理
  • 如何分辨AI生成的内容?AI生成内容检测工具对比实验
  • Clion中怎么切换不同的程序运行
  • 【C++初阶】C++入门(下)
  • 【3】迁移学习模型
  • 【工具分享】FOFA——网络空间测绘搜索引擎
  • [嵌入式 C 语言] 按位与、或、取反、异或
  • Android --- 运行时Fragment如何获取Activity中的数据,又如何将数据传递到Activity中呢?
  • Java后端开发(十三)-- Java8 stream的 orElse(null) 和 orElseGet(null)
  • L2 LangGraph_Components
  • 09.C2W4.Word Embeddings with Neural Networks
  • 硅谷甄选二(登录)
  • scipy库中,不同应用滤波函数的区别,以及FIR滤波器和IIR滤波器的区别
  • 简谈设计模式之建造者模式
  • 力扣 hot100 -- 动态规划(下)
  • 【计算机毕业设计】018基于weixin小程序实习记录
  • 力扣之有序链表去重
  • Apache配置与应用(优化apache)
  • 怎么将3张照片合并成一张?这几种拼接方法很实用!
  • YOLOv10改进 | 图像去雾 | MB-TaylorFormer改善YOLOv10高分辨率和图像去雾检测(ICCV,全网独家首发)
  • spring boot读取yml配置注意点记录
  • 电子电气架构 --- 关于DoIP的一些闲思 下
  • Java getSuperclass和getGenericSuperclass
  • ARM功耗管理标准接口之ACPI
  • 2024年网络监控软件排名|10大网络监控软件是哪些
  • 通过Arcgis从逐月平均气温数据中提取并计算年平均气温