Spring Injection static Attribute Value Mode

  • 2021-11-10 09:35:20
  • OfStack

Directory Spring injects static attribute value 1. Problem 2. Solution Spring dependency injection static static variable related problem 1. Spring does not support dependency injection static static variable 2. Spring how to inject value into static variable 3. Spring static injection 3 ways to search for the next solution on the Internet, a brief summary of the next several ways of implementation

Spring Inject static Attribute Value

This article describes how to inject values into static fields from properties files in Spring. In practical application, static attribute values in some tool classes need to be read from configuration files, so it is easier to use static methods provided by tool classes.

1. Problems

First define the properties in the properties file:


name = Inject a value to a static field

The instance variable is then injected with a value, typically with the @ Value annotation on the field:


@Value("${name}")
private String name;

However, if you apply yes to the static field, you will find that its value is null and the injection fails:


@Value("${name}")
private static String NAME_NULL;

This is because Spring does not support the @ Value annotation on the static field.

2. Solutions

The Spring @ Value annotation can be used on methods and is called by the Spring context after all Spring configurations and bean are loaded. If the method has multiple parameters, the value of each parameter is the value corresponding to the method annotation. If the parameter needs to obtain different values, you can add annotations on the parameter:


@Value("Test")
public void printValues(String s, String v){} //both 's' and 'v' values will be 'Test' 
@Value("Test")
public void printValues(String s, @Value("Data") String v){}
// s=Test, v=Data

With the above knowledge, we can modify the code as follows:


public class PropertyUtils { 
    @Value("${name1}")
    private String name; 
    private static String NAME_STATIC; 
    @Value("${name2}")
    public void setNameStatic(String name){
        PropertyController.NAME_STATIC = name;
    }
}

This time, the static variable NAME_STATIC was successfully assigned by the method.

Spring dependency injection static static variables related issues

1. Spring does not support dependency injection static static variables

In springframework, we can't use @ Autowired1 static variables to make it an spring bean, for example:


@Autowired
private static YourClass yourClass;

Try 1. yourClass can't be dependency injected in this state, and will throw the runtime exception java. lang. NullPointerException. Why? Static variables/class variables are not attributes of objects, but attributes of a class, while spring is based on dependency injection at the object level.

The use of static variables/class variables expands the scope of use of static methods. Static methods are not recommended in spring. The main purpose of dependency injection is to allow the container to generate an instance of an object and then use them throughout its lifecycle, while also making testing easier to work.

1 Once you use static methods, you no longer need to generate instances of this class, which makes testing more difficult, and you can't rely on injection to generate multiple instances with different dependencies for a given class. This static field is implicitly shared and is a global state of global, which is also not recommended for spring.

2. How does Spring inject values into static variables

spring does not allow/support injecting values into static variables, such as:


import org.springframework.beans.factory.annotation.Value;  
import org.springframework.stereotype.Component;    
@Component  
public class GlobalValue {    
    @Value("${mongodb.db}")  
    public static String DATABASE;    
}  

If you get GlobalValue. DATABASE, you get null


GlobalValue.DATABASE = null

So how can we solve this problem?

Fortunately, spring supports set method injection, so we can use non-static setter method to inject static variables. Such as:


import org.springframework.beans.factory.annotation.Value;  
import org.springframework.stereotype.Component;    
@Component  
public class GlobalValue {    
    public static String DATABASE;    
    @Value("${mongodb.db}")  
    public void setDatabase(String db) {  
        DATABASE = db;  
    } 
}  

Output:

GlobalValue.DATABASE = "mongodb database name"

3. Three ways of static injection of 3. Spring

(Note: MongoFileOperationUtil is encapsulated by its own 1 Mongodb file read-write tool class, which needs to rely on AdvancedDatastore object instance, dsForRW used to obtain Mongodb data source)

In springframework, we can't use @ Autowired1 static variables to make it an spring bean, for example:


@Autowired  
private static AdvancedDatastore dsForRW;  

Try 1. dsForRW can't be dependency injected in this state, and will throw the runtime exception java. lang. NullPointerException. Why? Static variables/class variables are not attributes of objects, but attributes of a class, while spring is based on dependency injection at the object level.

However, I prefer to encapsulate tool classes and annotate successful performance components through @ Component. However, method 1 in functional components is generally a static method, and static methods can only call static member variables, so there are the following problems. When encapsulating functional components, it will require the underlying service injection. What should I do?

Go to the Internet to search for solutions, and briefly summarize several ways to achieve 1

1. xml implementation


@Value("${name}")
private String name;
0

@Value("${name}")
private String name;
1

This method is suitable for WEB project based on XML configuration.

2. @ PostConstruct implementation


@Value("${name}")
private String name;
2

The @ PostConstruct annotated method executes after the class's constructor is loaded, that is, after the constructor is loaded, the init method is executed; (The @ PreDestroy annotation defines what to do before the container is destroyed)

This method is similar to configuring init-method and destory-method in xml, defining the operation of spring container before initializing bean and destroying container;

3. Add @ Autowired annotation to set method and @ Component annotation to class definition


import org.mongodb.morphia.AdvancedDatastore;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.stereotype.Component;   
@Component  
public class MongoFileOperationUtil {    
    private static AdvancedDatastore dsForRW;        
    @Autowired  
    public void setDatastore(AdvancedDatastore dsForRW) {  
        MongoFileOperationUtil.dsForRW = dsForRW;  
    }  
}  

First, Spring should be able to scan bean of AdvancedDatastore, and then injected by setter method;

Then note that there is no need to add @ Autowired annotation to member variables;


Related articles: