¿Por qué utilizar @PostConstruct?
-
25-09-2019 - |
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?
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 ...