1. Problems
I recently encountered the @Autiwired annotation injection behavior when writing the singleton pattern. After NULL
some research, I found that it is related to the initialization sequence of the class. Throw my question first:
//异步处理
public class AsyncManager {
@Autowired
ScheduledExecutorService scheduledExecutorService;
/**
* 操作延迟10毫秒
*/
private final int OPERATE_DELAY_TIME = 10;
/**
* 静态AsyncManager,单例
*/
private static AsyncManager manager = new AsyncManager();
/**
* 无参构造函数
*/
private AsyncManager(){}
/**
* 单例模式(饿汉式)
* @return AsyncManager
*/
public static AsyncManager getManager() {
return manager;
}
public void execute(TimerTask task) {
scheduledExecutorService.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
}
public SysUser login(String username, String password) {
AsyncManager.getManager().execute(new TimerTask() {
@Override
public void run() {
System.out.println(123);
}
});
return null;
}
Problems:
When calling AsyncManager.getManager().execute()
the method, it scheduledExecutorService
was NULL
not introduced.
the reason:
@Autowired
You must wait until the construction of this class is complete before setting it in from an external reference. When AsyncManager.getManager().execute()
the method is called , scheduledExecutorService
it has not been injected, which is why the @Autowired
annotation is recommended to be written on the constructor or method.
2. Class initialization order
From the above problems, the problems of class initialization and initialization sequence are extended.
First look at the test code:
public class Dog {
public static int a;
public int b;
static {
System.out.println("Static{} a, " + a++);
}
{
System.out.println("{} a, " + a++);
System.out.println("{} b, " + b++);
}
public Dog() {
System.out.println("Construct a, " + a++);
System.out.println("Construct b, " + b++);
}
public static void show() {
System.out.println("show() a, " + a++);
}
public void display() {
System.out.println("display() a, " + a++);
System.out.println("display() b, " + b++);
}
public static void main(String[] args) {
//Dog.show();
//System.out.println(Dog.a);
new Dog();
}
}
main
new Dog()
When executed in the method, the results of the program run are:
Static{} a, 0
{} a, 1
{} b, 0
Construct a, 2
Construct b, 1
The result shows that the initialization sequence is:
Static member variable-> Static code block-> Common member variable-> Common code block-> Constructor
If there is an inheritance relationship, the order is: parent class Static member variable-> parent class Static code block-> subclass Static member variable-> subclass Static code block-> parent class ordinary member variable-> parent class ordinary code block- > Subclass ordinary member variable-> Subclass ordinary code block-> Parent class constructor-> Constructor
3. When does the class initialize
- When creating an instance of a class, an object is new
- Access a static variable of a class or interface, or assign a value to the static variable
- Call the static method of the class
- reflection
- Initialize a subclass of a class (the parent class of the subclass will be initialized first)
- The startup class indicated when the JVM starts, that is, the class with the same file name and class name
When the class is initialized, please refer to the class loading order introduction in Java (ClassLoader)