Invocar Beans gerenciados por Spring em métodos estáticos (classes de ferramentas)

Cenas:

  • Ferramentas de pacote para facilitar o processamento de negócios
  • Beans gerenciados pela primavera precisam ser chamados na classe de ferramentas
  • A chamada de teste relata um problema de exceção de ponteiro nulo

Código preliminar da ferramenta:

@Component
public class ScriptExecuteContent {

@Autowired
private static SignRepository signRepository;

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

O código é deslumbrante e não há nada de errado com ele, mas ele será executado com uma exceção nula, porque o signRepository injetado aqui é nulo. Isso ocorre porque o método estático pertence à classe e o método comum pertence ao objeto. Spring a injeção é instanciada no contêiner. Variáveis ​​e estática existem em preferência aos objetos, portanto, as variáveis ​​estáticas injetadas diretamente no método estático são, na verdade, nulas.

Pensamento: 

 

O ciclo de vida do Spring Bean:

Instanciação e atribuição de propriedade correspondem à injeção de métodos construtores e setter, inicialização e destruição são dois estágios que os usuários podem personalizar e estender

  • Instanciação
  • Atribuição de atributo Preencher
  • Inicialização
  • Destruição

Inicialização ==> 4 métodos de transformação do objeto Bean:

Quando convocar a fase de destruição:

  • Instância única: quando o contêiner é fechado
  • Multi-instância: O contêiner não gerenciará este Bean e não chamará seu método de destruição
     

 

Solução um:

 @Autowired é usado no construtor

Sabemos que a anotação @Autowired pode anotar variáveis ​​de membros de classe, métodos e construtores para completar o trabalho de montagem automática.Assim, usar @Autowired no construtor.

@Component
public class ScriptExecuteContent {

private static SignRepository signRepository;

@Autowired
public ScriptExecuteContent(SignRepository signRepository) {
    ScriptExecuteContent.signRepository = signRepository;
}

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

 

Solução dois:

Use a anotação @PostConstruct

  • A partir da especificação Java EE5, duas anotações que afetam o ciclo de vida do Servlet foram adicionadas ao Servlet, @PostConstruct e @PreDestroy
  • Explicação desta anotação em Java: @PostConstruct Esta anotação está no pacote javax.annotation e é usada para decorar um método void () não estático
  • O método modificado por @PostConstruct será executado quando o servidor carregar o Servlet e só será executado uma vez pelo servidor
  • O método modificado por @PostConstruct é executado após o construtor e antes do método init ()
  • O método @PreDestroy () é executado depois que o método destroy () é executado
  • Regras de anotação @PostConstruct: Exceto para o caso especial de interceptor, nenhum parâmetro é permitido em outros casos, caso contrário, o framework spring reportará IllegalStateException; e se o valor de retorno for nulo, ele pode realmente ter um valor de retorno, pelo menos não relatar um erro, ele só será ignorado
  • Normalmente usamos o método de anotação @PostConstruct no framework Spring para anotar a ordem de execução do método de anotação em toda a inicialização do Bean: Construtor (método de construção) -> @Autowired (injeção de dependência) -> @PostConstruct (método anotado)

                                                                   

@Component
public class ScriptExecuteContent {

@Autowired
private SignRepository signRepository;

private static ScriptExecuteContent scriptExecuteContent;

@PostConstruct
public void update() {
    scriptExecuteContent = this;
    scriptExecuteContent.signRepository = this.signRepository;
}

public static String checkSign(String certNo, String acctNo, String instCode) {
    Sign sign = scriptExecuteContent.signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode);
    if (null != sign
            && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code())
            && DateUtil.getCurrentDate().before(sign.getExpireTime())) {
        return "1";
    } else {
        return "0";
    }
}
}

Exemplo 2:

@Component
public class StaticBook {
    private static String url;

    @Value("${test.str}")
    private String str;

    @PostConstruct
    public void update() {
        this.url = this.str;
    }

    public static BookTestTemp getValue(){
        return new BookTestTemp(1, "bookName", "123", url);
    }
}

 

Acho que você gosta

Origin blog.csdn.net/xiangwang2016/article/details/106148880
Recomendado
Clasificación