Stomp pit: @postconstruct, @Dependson, @Order annotation nested use case
When I was writing requirement code today, I met a problem about the loading priority of Sping Bean object. Combined with Spring source code, I roughly sum up three annotations commonly used when meeting the requirement of Bean loading Order: @postconstruct, @dependson and @Order.
The @order annotation
@Order
Annotations define the priority of the order of execution of beans in the Spring IOC container.
Use cases:
@Component
@Order(0)
public class Test01 {... }@Component
@Order(1)
public class Test02 {... }@Component
@Order(2)
public class Test03 {... }Copy the code
As shown in the code above, with the @Order annotation defining priority, the three Bean objects are loaded from the IOC container in the Order Test01, Test02, and Test03.
The @postconstruct annotation
@PostConstruct
Annotations can be used to modify a non-static return value of typevoid(eg:myInit()
).- This method (myInit()) is executed when the server loads the Servlet, and only once!
- This method (myInit()) is called after the constructor, before the init() method of the Servlet, and after the destroy() method of the Servlet.
Use cases:
@Component
public class Test {
@PostConstruct
private void init(a) {
/ / initialization
System.out.println("World!");
}
public Test(a){
System.out.println("Hello"); }}Copy the code
Output result:
Hello
World!
Copy the code
3. The role of @dependson annotations
- The function of this note is, as the name suggests, “who depends on whom.”
- Suppose we add to class Test02
@DependsOn(value = "test01")
The Spring IOC container will load Test01 first and then Test02.
As an example of a real business scenario, suppose you now have two classes Test01 and Test02 that need to be hosted by the Spring IOC container:
/** * Test01 is a class with 1 static variable */
@Component
public class Test01 {
// The property value of this static variable needs to be assigned by the Spring container. The value (hello) is defined in application.properties.
// Note: the @value annotation cannot inject property values into static variables (otherwise the injection result will be null)!
/ / so HELLO attribute Value into to add @ Value annotation on a setter method, reference articles: [https://blog.csdn.net/weixin_43591980/article/details/121503720]
public static String HELLO;
public static String WORLD;
@Value("${spring.test.hello}")/ / value for hello
public void setHELLO(String hello) {
HELLO = hello;
}
@Value("${spring.test.world}")/ / value for the world
public void setWORLD(String world) { WORLD = easak; }}Copy the code
Let’s look at the code for class Test02 (prerequisite: Class Test02 needs to be initialized first when our Spring Boot project starts!). :
/** * Test02 has one@PostConstructThe annotated init() initialization method and the no-argument constructor */
@Component
public class Test02 {
@PostConstruct
public void init(a){... }public Test02(a){... }}Copy the code
Business requirement: I need the console to print the value of the HELLO static variable in class Test01 when Test02’s no-argument constructor is loaded, and then theinit()
When the Test01 method executes, the console prints the value of the WORLD static variable in class Test01.
So my first thought was, just write it like this:
@PostConstruct
public void init(a){
System.out.println(Test01.HELLO);
}
public Test02(a){
System.out.println(Test02.WORLD);
}
Copy the code
But the final console print is:
null
null
Copy the code
Why? Why this result?
- Because,The Test02 class will be the first to be initialized when our Spring Boot project startsIn other words, the IOC container will load Test02 first, but Test01 has not been loaded into the container, and the two static variables HELLO and WORLD in Test01 have not passed
@Value
The annotation injects the property value, so the result should be null ~
Solution: Use @dependson annotations
Class Test02 has been modified:
@Component
@DependsOn(value = "test01")// Use this annotation to declare to the Spring container that the load of this class depends on Test01. When loading Test02, load Test01 first!
public class Test02 {
@PostConstruct
public void init(a){
System.out.println(Test01.HELLO);
}
public Test02(a){ System.out.println(Test01.WORLD); }}Copy the code
View the print result:
hello
world
Copy the code
Note: You can also use the @order annotation to specify a loading priority for class Test01 and class Test02.