Spring @PostConstruct vs.Atributo del método init


103

¿Hay alguna diferencia entre usar la @PostConstructanotación y declarar el mismo método que init-methoden la configuración de Spring XML?

Respuestas:


153

No, prácticamente no creo que haya ninguna diferencia, pero hay prioridades en la forma en que funcionan. @PostConstruct, init-methodson BeanPostProcessors.

  1. @PostConstructes una anotación JSR-250 mientras que init-methodes la forma en que Spring tiene un método de inicialización.
  2. Si tiene un @PostConstructmétodo, se llamará primero antes de llamar a los métodos de inicialización.
  3. Si su bean implementa InitializingBean y anula afterPropertiesSet, primero @PostConstructse llama, luego afterPropertiesSety luego init-method.

Para obtener más información, puede consultar la documentación de referencia de Spring .

Antes de las especificaciones JSR 250, el uso del método init en xml era la forma preferida, ya que desacopla las clases Java (beans) de cualquier clase / anotaciones específicas de Spring. Entonces, si está construyendo una biblioteca que no necesita depender de los beans de infraestructura de Spring luego se prefirió el uso del método init.Durante el método de creación, puede especificar el método que debe llamarse como método de inicialización.

Ahora, con la introducción de las especificaciones JSR 250 en Java EE y el soporte de primavera de estas anotaciones, la dependencia del marco de primavera se ha reducido hasta cierto punto.

Pero tengo que admitir que la adición de estas cosas aumenta la legibilidad del código, por lo que existen ventajas y desventajas en ambos enfoques.


22
Si un bean utiliza más de uno de esos métodos y depende del orden de inicialización, será terriblemente complejo e inmaterial.
Donal Fellows

2
@Donal Muy cierto. Solo estaba proporcionando información sobre cómo funciona esto.
Aravind A

1
Hay una diferencia importante: necesita configurar específicamente Spring para procesar anotaciones para que @PostConstruct funcione: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, pero necesita saber esto si planea tomar exámenes de certificación;)
S.Klechkovski

@DonalFellows - ¿Podría elaborar su respuesta? Me refiero a las dificultades que enfrenta si un bean se basa en el orden de inicialización. De hecho, quiero saber cuál es mejor. ¿PostConstruct o Bean (initMethod = "init") para hacer algunas cosas de inicialización desde un bean antes de que atienda cualquier solicitud?
Ayaskant

19

No hay ninguna diferencia real. Depende de cómo prefiera configurar su sistema, y ​​eso es una cuestión de elección personal. Yo mismo, prefiero usar @PostConstructanotaciones para mi propio código (ya que el bean solo está configurado correctamente después de que se llama al método) y lo uso init-methodal crear instancias de beans de bibliotecas que no son compatibles con Spring (¡no se pueden aplicar anotaciones allí, por supuesto!) pero puedo entender totalmente que la gente quiera hacerlo todo de una forma u otra.



3

Como puede ver en el siguiente diagrama de devolución de llamada del ciclo de vida de la creación de Bean .

Devolución de llamada del ciclo de vida de Bean Creation

Este 3 paso ocurre en la devolución de llamada del ciclo de vida de la creación de Bean:

  1. Se menciona que @PostConstructse llamará.
  2. Si InitializingBeanse implementa, entonces afterPropertiesSet()se llamará.
  3. Si la definición de bean contiene init-methodo @Bean(initmethod="..")entonces llama al método init.

Este diagrama es de Pro Spring 5: una guía detallada del marco de Spring y sus herramientas


3

No puede haber diferencia entre @PostConstructy init-methodporque @PostConstructse maneja en la postProcessAfterInitializationfase de inicialización del frijol ( AbstractAutowireCapableBeanFactory.initializeBean()método) por CommonAnnotationBeanPostProcessor, mientras que initel método es llamado después de la finalización de la postProcessBeforeInitializationfase (y, por este asunto, antes del comienzo de postProcessAfterInitializationla fase).
EDITAR : Entonces, la secuencia es: 1) postProcessBeforeInitializationfase, 2) initse llama al método, 3) postProcessAfterInitializationfase, que llama al @PostConstructmétodo

(Como nota al margen, una declaración de la respuesta aceptada

@PostConstruct, init-method son BeanPostProcessors

no es del todo correcto: @PostConstructes manejado por a BeanPostProcessor, el initmétodo no lo es.)

Habrá una diferencia si alguno (potencialmente personalizado) BeanPostProcessor, que está configurado con ( Ordered.getOrder()) para ejecutarse después CommonAnnotationBeanPostProcessor, está haciendo algo serio en su postProcessBeforeInitializationmétodo.
No hay ninguna diferencia con la configuración predeterminada de Spring BeanPostProcessorsporque todos los BeanPostProcessorsque están configurados para ejecutarse después CommonAnnotationBeanPostProcessor, no hacen nada en el postProcessBeforeInitializationmétodo.

En conclusión, la respuesta aceptada y similares son correctas ... en el 99% de los casos, y esta publicación es solo para rendir homenaje a un concepto "el diablo está en los detalles"


¡Hola! Esto es confuso, si PostConstruct se ejecuta antes que init-method, ¿cómo lo maneja postProcessAfterInitialization si el método init se ejecuta después de postProcessBeforeInitialization y antes de postProcessAfterInitialization ???
Maxrunner

@Maxrunner, perdón por la confusión y muchas gracias por hacérmelo saber. De hecho, nunca quise decir que PostConstruct se ejecuta antes que init-method. De todos modos, actualicé mi respuesta con algunas aclaraciones
igor.zh

2

Código completo aquí: https://github.com/wkaczurba/so8519187 ( spring-boot )

Usando anotaciones:

@Slf4j
@Component
public class MyComponent implements InitializingBean {

    @Value("${mycomponent.value:Magic}")
    public String value;

    public MyComponent() {
        log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
    }

    @PostConstruct
    public void postConstruct() {
        log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
    }

    @Override // init-method; overrides InitializingBean.afterPropertiesSet()
    public void afterPropertiesSet() {
        log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
    }   

    @PreDestroy
    public void preDestroy() {
        log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
    }
}

Nos consigue:

Actualizando org.springframework.context ...

MyComponent en el constructor: [nulo]
MyComponent en postConstruct: [Magic]
MyComponent en afterPropertiesSet: [Magic]
...

Registrando beans para la exposición JMX al inicio
Comenzó la DemoApplication en 0.561 segundos (JVM ejecutándose para 1.011)
Cerrando org.springframework.context .. . Eliminando el registro de beans expuestos a JMX al apagar

...
MyComponent en preDestroy: [Magic]

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.