Spring: Como injetar um valor em um campo estático?

91

Com esta aula

@Component
public class Sample {

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


}

Se eu tentar Sample.name, é sempre 'nulo'. Então eu tentei isso.

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á definido corretamente. Este é um bom caminho ou não? Se não, existe algo mais bom? E como fazer isso?

Whiteship
fonte
1
Isso não vai resolver; se a variável estática for usada antes da criação do objeto. por exemplo) se a variável estática for usada sob o bloco estático para construir o recurso, então o recurso será construído com null.
Kanagavelu Sugumar

Respostas:

116

Em primeiro lugar, os public staticnão- finalcampos são maus . O Spring não permite a injeção em tais campos por uma razão.

Sua solução alternativa é válida, você nem precisa de getter / setter, o privatecampo é o suficiente. Por outro lado, tente o seguinte:

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

(funciona com @Autowired/ @Resource). Mas, para lhe dar alguns conselhos construtivos: Crie uma segunda classe com privatecampo e getter em vez de public staticcampo.

Tomasz Nurkiewicz
fonte
9
Para "campos públicos estáticos não finais são ruins", você poderia me dar algumas referências?
Anderson
7
Não final significa que você pode modificar o valor do campo, o que, para um campo estático, implica lidar com a simultaneidade de thread - também conhecido como dor na pilha.
Xavier Portebois
Como usar @Value com bloco estático? Por favor, guie-nos ... Atenciosamente, Neha
4
Apenas para sua informação: O código acima irá causar uma violação de estilo Sonar / Check (se você estiver incomodado com esse tipo de coisa) já que você tem um método de instância gravando em um campo estático.
Neil de
É possível imitar o aspecto final usando um setter estático que só definirá o valor se ele for nulo no momento. Portanto, você permite apenas uma modificação do campo. (que obviamente foi tornado privado e use um getter para acessá-lo). Spring pode chamar métodos estáticos em sua fase de configuração (XML ou Anotação).
Walfrat
0

Este é o meu código de amostra para carregar variável 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
fonte
-2

Spring usa injeção de dependência para preencher o valor específico quando encontra a anotação @Value. No entanto, em vez de passar o valor para a variável de instância, ele é passado para o configurador implícito. Este setter então lida com a população de nosso 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
fonte