Issue
I have a class that uses a static initialization block that does some stuff. My understanding is that this block is executed when the class is loaded which is triggered by calling some methods from it.
My question is if this static initialization can be triggered from frameworks like spring that look at the classes to examine their annotations and so on?
Solution
Classpath scanning does not trigger static initialization blocks but creating components does:
@Component
public class ComponentClass{
static{
System.out.println("this is printed");
}
}
public class OtherClass{
static{
System.out.println("this is not printed");
}
}
From JLS 8.7:
A static initializer declared in a class is executed when the class is initialized (§12.4.2). Together with any field initializers for class variables (§8.3.2), static initializers may be used to initialize the class variables of the class.
Note that it says initialized
and not loaded
.
Class initialization happens when a static member (method or variable) or a constructor is executed. When accessing metadata of a class using reflection, those classes are not necessarily initialized, depending on what of the class is accessed via reflection.
This is defined in JLS 12.4.1:
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
- T is a class and an instance of T is created.
- T is a class and a static method declared by T is invoked.
- A static field declared by T is assigned.
- A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.
Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization.
Spring just scans for classes in that package and looks for annotations (like @Component
) in those classes.
If Spring finds such components, it creates instances of those which initializes the classes.
Note from chrylis -cautiouslyoptimistic-:
Note that in certain special cases (mostly Spring Boot auto-configuration), Spring might not even load the class at all. (It sometimes performs direct bytecode analysis to avoid loading classes that touch optional dependencies.)
Answered By - dan1st