一、定义

resolveBeforeInstantiation 是 Spring 框架中 AbstractAutowireCapableBeanFactory 类的核心方法之一,它在 Bean 的实例化阶段扮演了关键角色。它的核心作用是:在 Bean 的默认实例化流程开始之前,提供一个扩展点,允许开发者通过 InstantiationAwareBeanPostProcessor 接口提前创建并返回代理对象。如果成功返回 Bean的代理对象,Spring 将跳过后续的默认实例化、属性填充和初始化流程,直接使用该代理对象

二、方法的核心作用

1、在Bean创建之前进行拦截

  • 在 Spring 的 Bean 生命周期中,Bean 的创建通常分为以下几个阶段:

    • a、实例化(Instantiation):通过构造器或工厂方法创建 Bean 的实例。

    • b、属性填充(Population):注入依赖的属性和值。

    • c、初始化(Initialization):调用初始化方法(如 @PostConstruct、InitializingBean 接口)

  • resolveBeforeInstantiation 方法发生在 实例化阶段之前。它允许开发者通过 InstantiationAwareBeanPostProcessor 接口在默认实例化逻辑执行前,直接生成一个 Bean 的代理对象

2、完全替代默认实例化逻辑

  • 如果 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法返回了一个非 null 的 Bean 实例:

    • Spring 将跳过默认的实例化(如构造器调用)、属性填充和初始化流程

    • 直接使用该实例作为最终的 Bean,仅执行后续的 BeanPostProcessor 后置处理(如 @PostConstruct)

三、方法的关键应用场景

1、动态生成代理对象

  • 典型场景:在 Spring AOP 中,某些 Bean 需要被代理(如被 @Transactional 注解标记的类)

  • 实现方式:

    • 通过 InstantiationAwareBeanPostProcessor,在 postProcessBeforeInstantiation 方法中生成代理对象

    • 如果成功返回代理对象,Spring 将直接使用它,避免后续实例化和属性填充的开销

2、从缓存或外部资源加载 Bean

  • 典型场景:某些 Bean 的实例需要从缓存、数据库或远程服务中加载,而非通过构造器创建。

  • 实现方式:

    • 在 postProcessBeforeInstantiation 方法中,直接从缓存或外部资源获取 Bean 实例

    • 如果获取成功,直接返回该实例

3、完全自定义 Bean 的创建逻辑

  • 典型场景:某些复杂对象的创建需要特殊处理(如依赖外部配置或动态生成代码)。

  • 实现方式:

    • 在 postProcessBeforeInstantiation 方法中,通过自定义逻辑生成 Bean 实例。

    • 例如:根据条件动态选择实现类,或使用反射工具生成对象。

四、方法的具体实现逻辑

1、条件检查

  • 检查 beforeInstantiationResolved 标志:

    • 该标志记录是否已尝试过提前实例化。

    • 如果为 Boolean.FALSE,直接跳过,避免重复处理。

  • 检查 Bean 是否为“合成”的:

    • 合成 Bean(如 Spring 内部生成的 Bean)不参与此流程。
  • 检查是否存在 InstantiationAwareBeanPostProcessor:

    • 仅当存在注册的 InstantiationAwareBeanPostProcessor 时,才执行后续逻辑。

2、调用 postProcessBeforeInstantiation

  • 遍历所有 InstantiationAwareBeanPostProcessor,依次调用其 postProcessBeforeInstantiation 方法。

  • 第一个返回非 null 的处理器将决定最终的 Bean 实例。

  • 如果所有处理器均返回 null,则继续执行默认实例化流程。

3、后续处理

  • 如果成功获取 Bean 实例,执行 BeanPostProcessor 的 postProcessAfterInitialization 方法。

  • 最终更新 beforeInstantiationResolved 标志,避免重复处理。

五、实际案例:Spring AOP 中的代理生成

1、场景描述

  • 当一个 Bean 被 AOP 切面(如 @Transactional)拦截时,Spring 需要为其创建代理对象

  • 代理对象的生成可能发生在两个阶段:

    • 提前生成:通过 resolveBeforeInstantiation 在实例化前生成。

    • 后置生成:在初始化后通过 BeanPostProcessor 生成。

2、为何选择提前生成 ?

  • 性能优化:提前生成代理可以避免不必要的实例化和属性填充操作。

  • 解决循环依赖:某些情况下,提前生成代理能避免因代理延迟导致的循环依赖问题。

3、实现代码(简化版)

public class AnnotationAwareAspectJAutoProxyCreator implements InstantiationAwareBeanPostProcessor {

    @Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 检查是否需要为当前 Bean 创建代理
if (shouldProxy(beanClass, beanName)) {
// 生成代理对象
return createProxy(beanClass, beanName);
}
return null;
}
}

六、注意事项

1、慎用 postProcessBeforeInstantiation:

  • 该方法会完全跳过 Spring 的默认实例化流程,可能导致依赖注入(如 @Autowired)失效。

  • 仅当需要完全控制 Bean 的创建逻辑时才使用此扩展点。

2、与 BeanPostProcessor 的区别:

  • BeanPostProcessor 作用于 Bean 的初始化前后,无法替代实例化逻辑。

  • InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 可以完全替代实例化。

3、性能影响:

  • 频繁调用复杂的 postProcessBeforeInstantiation 逻辑可能影响启动性能。

  • 建议结合缓存或懒加载机制优化。

七、总结

resolveBeforeInstantiation 是 Spring Bean 生命周期中一个重要的扩展点,它允许开发者在默认实例化流程之前完全自定义 Bean 的创建逻辑。通过实现 InstantiationAwareBeanPostProcessor 接口,可以动态生成代理对象、从外部资源加载 Bean 或实现其他高级定制需求。理解该方法的作用和实现原理,有助于深入掌握 Spring 的扩展机制,并在实际开发中灵活应对复杂场景。

Spring 的 resolveBeforeInstantiation 方法作用详解的更多相关文章

  1. Spring各种注解标签作用详解

    @Autowired和@Resource等注解是将Spring容器中的bean注入到属性,而@Component等注解是将bean放入Spring容器中管理. @Autowired spring2.1 ...

  2. Spring Boot 之使用 Json 详解

    Spring Boot 之使用 Json 详解 简介 Spring Boot 支持的 Json 库 Spring Web 中的序列化.反序列化 指定类的 Json 序列化.反序列化 @JsonTest ...

  3. Spring Boot启动命令参数详解及源码分析

    使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...

  4. SpringBoot之Spring@Value属性注入使用详解

    在使用Spring框架的项目中,@Value是使用比较频繁的注解之一,它的作用是将配置文件中key对应的值赋值给它标注的属性.在日常使用中我们常用的功能都比较简单,本篇文章系统的带大家来了解一下@Va ...

  5. Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!

    点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...

  6. spring cache 学习——@CachePut 使用详解

    1. 功能说明 当需要在不影响方法执行的情况下更新缓存时,可以使用 @CachePut,也就是说,被 @CachePut 注解的缓存方法总是会执行,而且会尝试将结果放入缓存(当然,是否真的会缓存还跟一 ...

  7. CentOS 6.3下Samba服务器的安装与配置方法(图文详解)

    这篇文章主要介绍了CentOS 6.3下Samba服务器的安装与配置方法(图文详解),需要的朋友可以参考下   一.简介  Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件, ...

  8. jQuery操纵DOM元素属性 attr()和removeAtrr()方法使用详解

    jQuery操纵DOM元素属性 attr()和removeAtrr()方法使用详解 jQuery中操纵元素属性的方法: attr(): 读或者写匹配元素的属性值. removeAttr(): 从匹配的 ...

  9. [转]js中几种实用的跨域方法原理详解

    转自:js中几种实用的跨域方法原理详解 - 无双 - 博客园 // // 这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同 ...

  10. [置顶] 深入浅出Spring(三) AOP详解

    上次的博文深入浅出Spring(二) IoC详解中,我为大家简单介绍了一下Spring框架核心内容中的IoC,接下来我们继续讲解另一个核心AOP(Aspect Oriented Programming ...

随机推荐

  1. vim系列-文本操作篇

    基数行与偶数行分组 使用Vim的替换命令,可以轻松地将基数行和偶数行分组: %s/\(^.*$\)\n\(^.*$\)/\1 \2/g 然后,删除所有的基数行: %s/^.*$\n\(^.*$\)/\ ...

  2. Win7远程桌面连接不上

    Windows远程桌面连接不上有多种情况,当完成基本设置后,如果连不上,那么最可能的情况是防火墙和网络设置不匹配. 1. 检查一下Window防火墙中远程桌面的设置,默认情况下只允许"家庭/ ...

  3. java子类父类有相同的方法优先调用子类-重写-递归

    子类和父类有相同的方法,优先调用子类.如果子类没有,父类. package studyDemo9yue; public class study01 { public static void main( ...

  4. 玩转云端 | 天翼云边缘安全加速平台AccessOne实用窍门之多款产品管理难?一站式平台管理全hold住!

    随着数字化转型深入推进,企业信息化建设成效显著,同时其所面临的安全与性能挑战也日趋复杂,既要确保业务系统的安全性,同时也要提供快速.流畅的用户体验,以提升用户满意度和业务竞争力. 在传统的解决方案中, ...

  5. SqlServer中根据某几列获取重复的数据将其删除并保留最新一条

    有时候,我们某个数据表中,可能有几列的数据都是一样的,此时我们可能想查询出这几列数据相同的所有数据行,并保留最新一条,将其他重复的数据删除. 1.ROW_NUMBER函数 假设我们有如下数据表: 此时 ...

  6. jar脚本练习

    javaServer.sh #!/bin/bash export JAVA_HOME=/u01/java_home/jdk1.8.0_131 export APP_HOME=/u01/app expo ...

  7. Lucas 定理证明与扩展

    Lucas 定理及其证明.扩展 \[\binom{n}{m}\equiv\binom{n/p}{m/p}\binom{n\bmod p}{m\bmod p}\pmod p,\text{where}\ ...

  8. 使用mongodb、Kafka保存mqtt消息

    一.引言 随着物联网技术的迅猛发展,大量的设备和传感器产生了海量的数据.本文利用了 MQTT.Kafka 和 MongoDB 各自的优点,满足实时数据处理和大规模数据存储的需求. 如图: 二.总结 优 ...

  9. 功率MOS管的参数说明

    图解功率MOS管的每一个参数!   最大额定参数 最大额定参数,所有数值取得条件(Ta=25℃) VDSS 最大漏-源电压 在栅源短接,漏-源额定电压(VDSS)是指漏-源未发生雪崩击穿前所能施加的最 ...

  10. Kettle - 使用案例

    原文链接:https://blog.csdn.net/gdkyxy2013/article/details/117106691 案例一:把seaking的数据按id同步到seaking2,seakin ...