Spring是否会触发类的静态初始化块执行?
Spring类扫描是否会触发静态初始化块执行
核心结论
绝大多数场景下,Spring扫描类注解的动作不会触发目标类的静态初始化块执行,只有当Spring实际需要实例化类、调用类静态方法/访问类静态字段时,才会触发类的初始化流程,执行静态块。
具体原因
Java的类加载流程分为3个核心阶段:
- 加载:读取类的字节码文件,在内存中生成对应的Class对象
- 链接:验证字节码合法性、为静态变量分配内存赋默认值、解析符号引用
- 初始化:执行静态初始化块、给静态变量赋程序员指定的初始值
Spring扫描类注解的动作,只会用到第一阶段加载得到的Class对象的元数据,不会触发类的初始化阶段:
Spring底层扫描类时,默认通过ASM框架直接读取字节码文件的注解信息,甚至不会走JVM的类加载流程加载该类;即便是需要通过
Class.forName获取Class对象的场景,Spring也会调用带3个参数的重载方法Class.forName(className, false, classLoader),其中第二个参数initialize设为false,明确告知JVM不要执行类的初始化动作。
特殊例外情况
只有两种情况Spring扫描过程可能意外触发静态块执行:
- 你自定义了BeanDefinition扫描逻辑,调用
Class.forName时主动将initialize参数设为true - 类的字节码本身存在特殊字节码增强逻辑,在类加载的链接阶段就主动触发了初始化操作(这种情况和Spring本身无关,属于类本身的特殊实现)
代码验证示例
你可以用下面的代码自行验证:
// 带静态块的测试类 @Component public class TestStaticClass { static { System.out.println("静态初始化块被执行了"); } } // Spring启动类 @SpringBootApplication public class DemoApplication { public static void main(String[] args) { // 只扫描BeanDefinition,不实例化 GenericApplicationContext context = new GenericApplicationContext(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.scan("com.example.demo"); System.out.println("Bean扫描完成,还未实例化"); // 刷新上下文才会实例化Bean,此时才会打印静态块的内容 context.refresh(); } }
运行后可以看到,扫描完成时不会打印静态块的输出,只有刷新上下文实例化Bean时才会触发静态块执行。
内容的提问来源于stack exchange,提问作者MadScientist
相关产品推荐
相关产品推荐

