java - ejemplo - ¿Por qué usar @PostConstruct?
@postconstruct spring (5)
Además, la inicialización basada en constructor no funcionará como se esperaba cuando se trata de algún tipo de proxy o comunicación remota.
Se llamará al ct cada vez que se deserializa un EJB y cada vez que se crea un nuevo proxy para él ...
En un bean administrado, se llama a @PostConstruct
después del constructor de objetos Java normal.
¿Por qué usaría @PostConstruct
para inicializar por bean, en lugar del propio constructor regular?
Considere el siguiente escenario:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Dado que se debe crear una instancia de Car antes de la inyección de campo, el motor de punto de inyección aún es nulo durante la ejecución del constructor, lo que da como resultado una excepción NullPointerException.
Este problema se puede resolver mediante la inyección de dependencia JSR-330 para inyección de constructor Java o Anotaciones comunes JSR 250 para la anotación del método Java @PostConstruct.
@PostConstruct
JSR-250 define un conjunto común de anotaciones que se ha incluido en Java SE 6.
La anotación PostConstruct se usa en un método que debe ejecutarse después de que se realiza la inyección de dependencias para realizar cualquier inicialización. Este método DEBE ser invocado antes de que la clase se ponga en servicio. Esta anotación DEBE ser compatible con todas las clases que admiten la inyección de dependencia.
JSR-250 Cap. 2.5 javax.annotation.PostConstruct
La anotación @PostConstruct permite la definición de los métodos que se ejecutarán después de que la instancia haya sido instanciada y se hayan realizado todas las inyecciones.
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 posteriores a la construcción es una cuestión simple de encontrar todos los métodos anotados con @PostConstruct e invocarlos 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 posteriores a la construcción se debe realizar después de que se haya completado la creación de instancias y la inyección.
El principal problema es que:
en un constructor, la inyección de las dependencias aún no ha ocurrido *
* obviamente excluyendo Inyección Constructor
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
se eliminaron completamente en Java 11 .
Para seguir usándolos, deberá agregar 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 toda su inicialización en el constructor, entonces @PostConstruct
es de hecho redundante.
Sin embargo, si su clase tiene sus dependencias inyectadas usando métodos de establecimiento, entonces el constructor de la clase no puede inicializar completamente el objeto, y algunas veces es necesario realizar alguna inicialización después de que se hayan llamado a todos los métodos de establecimiento, de ahí el caso de uso de @PostConstruct
.
porque cuando se llama al constructor, el bean aún no está inicializado, es decir, no se inyectan dependencias. En el método
@PostConstruct
, el bean está completamente inicializado y puede usar las dependencias.porque este es el contrato que garantiza que este método se invocará solo una vez en el ciclo de vida del bean. Puede suceder (aunque sea poco probable) que el contenedor
@PostConstruct
un bean varias veces en su funcionamiento interno, pero garantiza que se invocará@PostConstruct
solo una vez.