Java框架源码中代码块执行顺序严格遵循JVM规则:静态块用于类加载时一次性初始化,构造块与字段初始化共同确保对象实例状态统一,构造方法体处理定制逻辑,普通代码块仅限方法内作用域控制。

Java 中代码块执行顺序在框架源码中不是“被特意设计”的显性结构,而是被隐式依赖和严格遵循的底层机制。Spring、MyBatis、Hibernate 等主流框架大量利用静态块做类级预热、用构造块统一对象状态、靠字段初始化与构造方法协同完成 Bean 构建——这些都不是巧合,而是对 JVM 初始化规则的精准调用。
静态代码块:框架启动时的“第一道工序”
框架核心类(如 SpringApplication、SqlSessionFactoryBuilder)普遍用静态块完成不可变资源的单次加载:
- Spring Boot 的
SpringApplication类中,静态块会提前注册默认的ApplicationContextInitializer和ApplicationRunner类型; - MyBatis 的
Configuration类用静态块初始化默认类型别名(如"int"→Integer.class),避免每次创建SqlSessionFactory时重复注册; - Hibernate 的
MetadataSources通过静态块预设 JDBC 方言映射表。
这些操作都满足一个前提:只执行一次、不依赖实例、必须在任何 Bean 创建前就绪——这正是静态块的语义契约。
多个静态块按源码顺序执行,框架作者常借此控制初始化依赖链。例如先加载基础枚举,再初始化缓存管理器,最后注册监听器,顺序不能错。
立即学习“Java免费学习笔记(深入)”;
构造代码块:Bean 实例化过程中的“隐形模板”
框架内部大量使用构造块来抹平构造器差异,统一新对象初始状态:
- Spring 的
AbstractBeanDefinition子类(如RootBeanDefinition)用{ this.autowireMode = AUTOWIRE_NO; }这类构造块,确保每个实例默认关闭自动装配,无需在每个构造方法里重复写; - MyBatis 的
MappedStatement构造过程中,实例块负责设置fetchSize、timeout等默认值,无论调用哪个重载构造器,这些字段总在构造方法体运行前就已就位; - Lombok 的
@Data编译后生成的字节码,本质就是把字段初始化逻辑“注入”到构造块位置,而非塞进构造方法体——这正契合 JVM 要求“字段赋值 & 构造块先于构造方法体”的顺序。
注意:构造块在编译后会被复制到每一个构造方法开头(紧随 super() 或 this() 调用之后),所以即使框架提供多个构造签名,行为依然一致。
字段显式初始化 + 构造块 + 构造方法:Bean 构建三段式
Spring 的 DefaultListableBeanFactory 初始化流程就是一个典型例子:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory {
// ① 字段显式初始化(在构造块之前?不——它们同属实例初始化阶段,按源码顺序交替)
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
// ② 构造代码块(统一设置基础状态)
{
this.allowBeanDefinitionOverriding = true;
this.allowCircularReferences = true;
}
// ③ 构造方法体(处理传入参数,完成定制化)
public DefaultListableBeanFactory() {
super();
// 此处才做依赖注入准备、事件发布器注册等后期动作
}
}JVM 执行 new DefaultListableBeanFactory() 时实际顺序是:
-
beanDefinitionMap = new ConcurrentHashMap<>() - 构造块中两行赋值
-
super()(进入父类构造链) -
super()返回后,执行本类构造方法体
这种分层设计让框架既能保证基础结构可靠(靠字段+构造块),又能保留扩展入口(靠构造方法体)。
普通代码块:仅用于方法内逻辑隔离,与初始化无关
框架源码中常见普通代码块,但它不参与对象生命周期控制:
- 在
doCreateBean()方法里用{ Object earlySingleton = ... }限定临时引用作用域,防止意外泄露; - MyBatis 的
Executor实现中,query()方法用{ try (AutoCloseable c = ...) { ... } }显式控制资源生命周期; - 这些块纯粹是语法糖,谁写在前面谁先执行,和类加载、new 对象完全解耦。
它们的存在只是为了代码清晰或资源安全,不会影响 Bean 的创建顺序,也不该被误读为“初始化环节”。
框架开发者清楚区分这三类块的职责边界:
- 静态块 → “这个类准备好没?”
- 构造块 + 字段初始化 → “这个对象刚出生时长什么样?”
- 构造方法体 → “它出生后要立刻做什么?”
- 普通块 → “这段代码跑的时候,变量别乱串”。
不复杂但容易忽略细节。


















