Spring: ¿Cómo inyectar un valor a un campo estático?

90

Con esta clase

@Component
public class Sample {

    @Value("${my.name}")
    public static String name;


}

Si lo intento Sample.name, siempre es "nulo". Así que intenté esto.

public class Sample {

    public static String name;

    @PostConstruct
    public void init(){
        name = privateName;
    }

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

    public String getPrivateName() {
        return privateName;
    }

    public void setPrivateName(String privateName) {
        this.privateName = privateName;
    }  

}

Este código funciona. Sample.nameestá configurado correctamente. ¿Es esta buena forma o no? Si no es así, ¿hay algo más bueno? ¿Y, cómo hacerlo?

Whiteship
fuente
Esto no resolverá; si la variable estática se usa antes de la creación del objeto. p. ej.) si la variable estática se usa en un bloque estático para construir el recurso, entonces el recurso se construirá con nulo.
Kanagavelu Sugumar

Respuestas:

115

En primer lugar, los public staticno finalcampos son malos . Spring no permite inyectar en tales campos por una razón.

Su solución es válida, ni siquiera necesita getter / setter, el privatecampo es suficiente. Por otro lado, intente esto:

@Value("${my.name}")
public void setPrivateName(String privateName) {
    Sample.name = privateName;
}  

(trabaja con @Autowired/ @Resource). Pero para darle un consejo constructivo: cree una segunda clase con privatecampo y captador en lugar de public staticcampo.

Tomasz Nurkiewicz
fuente
9
Para "los campos públicos estáticos no finales son malos", ¿podría darme algunas referencias?
Anderson
7
No final significa que puede modificar el valor del campo, lo que, para un campo estático, implica el manejo de la concurrencia de subprocesos, también conocido como dolor en la pila.
Xavier Portebois
¿Cómo usar @Value con bloque estático? Guíanos amablemente ... Saludos, Neha
4
Solo para su información: el código anterior causará una violación de Sonar / Checkstyle (si le molesta ese tipo de cosas) ya que tiene un método de instancia escribiendo en un campo estático.
Neil
Es posible imitar el aspecto final usando un setter estático que solo establecerá el valor si actualmente es nulo. De modo que solo permite una modificación del campo. (que por supuesto se ha hecho privado y usa un getter para acceder a él). Spring puede llamar al método estático en su fase de configuración (XML o Anotación).
Walfrat
0

Este es mi código de muestra para cargar variable estática

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class OnelinkConfig {
    public static int MODULE_CODE;
    public static int DEFAULT_PAGE;
    public static int DEFAULT_SIZE;

    @Autowired
    public void loadOnelinkConfig(@Value("${onelink.config.exception.module.code}") int code,
            @Value("${onelink.config.default.page}") int page, @Value("${onelink.config.default.size}") int size) {
        MODULE_CODE = code;
        DEFAULT_PAGE = page;
        DEFAULT_SIZE = size;
    }
}
Thành Nguyễn
fuente
-2

Spring usa la inyección de dependencia para completar el valor específico cuando encuentra la anotación @Value. Sin embargo, en lugar de entregar el valor a la variable de instancia, se entrega al establecedor implícito. Este establecedor luego maneja la población de nuestro valor NAME_STATIC.

    @RestController 
//or if you want to declare some specific use of the properties file then use
//@Configuration
//@PropertySource({"classpath:application-${youeEnvironment}.properties"})
public class PropertyController {

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

    private static String NAME_STATIC;

    @Value("${name}")
    public void setNameStatic(String name){
        PropertyController.NAME_STATIC = name;
    }
}
Vitalii Shramko
fuente