Pregunta

En un bean gestionado, @PostConstruct se llama después del objeto regular de constructor de Java.

Por qué iba a utilizar para inicializar @PostConstruct de frijol, en lugar de la propia constructora regular?

¿Fue útil?

Solución

  • porque cuando se llama al constructor, el grano aún no está inicializado - se inyectan es decir, no hay dependencias. En el método @PostConstruct el grano está totalmente inicializado y puede utilizar las dependencias.

  • porque este es el contrato que garantiza que este método será invocado sólo una vez en el ciclo de vida de frijol. Puede suceder (aunque poco probable) que se crea una instancia de frijol múltiples veces por el recipiente en su trabajo interno, pero garantiza que @PostConstruct será invocado sólo una vez.

Otros consejos

El principal problema es que:

  

en un constructor, aún no ha tenido lugar la inyección de las dependencias *

* excluyendo obviamente Constructor de inyección


ejemplo del 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 y @PreDestroy en Java 11 .

Para seguir usándolas, necesitará añadir el javax.annotation-api JAR a sus dependencias.

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'

Si su clase realiza todo de su inicialización en el constructor, a continuación, @PostConstruct es de hecho redundante.

Sin embargo, si su clase tiene sus dependencias inyectaron usando métodos setter, a continuación, el constructor de la clase no puede inicializar plenamente el objeto y, a veces algunas de las necesidades de inicialización que se deben realizar después de que todos los métodos setter han sido llamados, por lo tanto, el caso de uso de @PostConstruct.

Considere el siguiente escenario:

public class Car {
  @Inject
  private Engine engine;  

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

Desde tiene coches para ser instanciado antes de la inyección campo, el motor de punto de inyección sigue siendo nula durante la ejecución del constructor, resultando en una NullPointerException.

Este problema se puede resolver, ya sea por JSR-330 Inyección de dependencias para Java la inyección de constructor o JSR 250 Anotaciones comunes para el método de anotación de Java @PostConstruct.

@PostConstruct

JSR-250 define un conjunto común de anotaciones que ha sido incluido en Java SE 6.

  

La anotación PostConstruct se utiliza en un método que necesita ser   ejecutado tras la inyección de dependencia se hace para realizar cualquier   inicialización. Este método debe ser invocado ante la clase se pone   en servicio. Esta anotación deberá ser apoyado en todas las clases que   apoyar la inyección de dependencias.

     

JSR-250 Cap. 2,5 javax.annotation.PostConstruct

La anotación @PostConstruct permite la definición de métodos para ser ejecutado después de que la instancia se ha instanciado y se han realizado todas inyecta.

public class Car {
  @Inject
  private Engine engine;  

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

En lugar de realizar la inicialización en el constructor, el código se mueve a un método anotado con @PostConstruct.

El procesamiento de los métodos de post-construcción es un simple cuestión de encontrar todos los métodos anotado con @PostConstruct e invocando ellos a su 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);
        }
      });
}

El procesamiento de los métodos de post-construcción tiene que ser realizado después de la instanciación y la inyección se han completado.

También basado inicialización del constructor no funcionará como se pretende siempre que se implicase una especie de proxy o de interacción remota.

El CT se llamará cada vez que un EJB se deserialized, y cada vez que un nuevo proxy se crea para ella ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top