Pergunta

Em um feijão gerenciado, @PostConstruct é chamado após o construtor de objeto Java regular.

Por que eu usaria @PostConstruct Inicializar por Bean, em vez do próprio construtor regular?

Foi útil?

Solução

  • Porque quando o construtor é chamado, o feijão ainda não foi inicializado - ou seja, nenhuma dependência é injetada. No @PostConstruct Método O feijão é totalmente inicializado e você pode usar as dependências.

  • Porque esse é o contrato que garante que esse método seja invocado apenas uma vez no ciclo de vida do feijão. Pode acontecer (embora improvável) que um feijão seja instanciado várias vezes pelo contêiner em seu trabalho interno, mas garante que isso @PostConstruct será chamado apenas uma vez.

Outras dicas

o a Principal O problema é isso:

Em um construtor, a injeção das dependências ainda não ocorreu*

*Obviamente excluindo a injeção de construtor


Exemplo do mundo real:

public class Foo {

    @Inject
    Logger LOG;

    @PostConstruct
    public void fooInit(){
        LOG.info("This will be printed; LOG has already been injected");
    }

    public Foo() {
        LOG.info("This will NOT be printed, LOG is still null");
        // NullPointerException will be thrown here
    }
}

IMPORTANTE: @PostConstruct e @PreDestroy foram completamente Removido em Java 11.

Para continuar usando, você precisará adicionar o javax.annotation-api Jar com suas dependências.

Maven

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

Gradle

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'

Se sua classe executar toda a sua inicialização no construtor, então @PostConstruct é realmente redundante.

No entanto, se sua classe tiver suas dependências injetadas usando métodos Setter, o construtor da classe não pode inicializar completamente o objeto e, às vezes @PostConstruct.

Considere o seguinte cenário:

public class Car {
  @Inject
  private Engine engine;  

  public Car() {
    engine.initialize();  
  }
  ...
}

Como o CAR deve ser instanciado antes da injeção de campo, o motor do ponto de injeção ainda é nulo durante a execução do construtor, resultando em uma NullPointerException.

Este problema pode ser resolvido por Injeção de dependência JSR-330 para Java injeção de construtor ou anotações comuns do JSR 250 para a anotação do método Java @PostConstruct.

@PostConstruct

O JSR-250 define um conjunto comum de anotações que foram incluídas no Java SE 6.

A anotação pós -construção é usada em um método que precisa ser executado após a injeção de dependência ser feita para executar qualquer inicialização. Este método deve ser chamado antes que a classe seja colocada em serviço. Esta anotação deve ser suportada em todas as classes que suportam a injeção de dependência.

JSR-250 cap. 2.5 javax.annotation.postconstruct

A anotação @PostConstruct permite que a definição de métodos seja executada após a instância ter sido instanciada e todos os injetos tenham sido realizados.

public class Car {
  @Inject
  private Engine engine;  

  @PostConstruct
  public void postConstruct() {
    engine.initialize();  
  }
  ...
} 

Em vez de executar a inicialização no construtor, o código é movido para um método anotado com @PostConstruct.

O processamento dos métodos pós-construção é uma questão simples de encontrar todos os métodos anotados com @PostConstruct e invocá-los por sua vez.

private  void processPostConstruct(Class type, T targetInstance) {
  Method[] declaredMethods = type.getDeclaredMethods();

  Arrays.stream(declaredMethods)
      .filter(method -> method.getAnnotation(PostConstruct.class) != null) 
      .forEach(postConstructMethod -> {
         try {
           postConstructMethod.setAccessible(true);
           postConstructMethod.invoke(targetInstance, new Object[]{});
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {      
          throw new RuntimeException(ex);
        }
      });
}

O processamento dos métodos pós-construção deve ser realizado após a conclusão da instanciação e injeção.

Além disso, a inicialização baseada no construtor não funcionará como pretendido sempre que algum tipo de proxy ou remoção estiver envolvido.

O CT será chamado sempre que um EJB for desseerializado e sempre que um novo proxy for criado para ele ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top