Attribut Spring @PostConstruct et méthode init


103

Y a-t-il une différence entre l'utilisation de l' @PostConstructannotation et la déclaration de la même méthode que init-methoddans la configuration Spring XML?

Réponses:


153

Non pratiquement, je ne pense pas qu'il y ait de différence, mais il y a des priorités dans leur façon de travailler. @PostConstruct, init-methodsont des BeanPostProcessors.

  1. @PostConstructest une annotation JSR-250, tandis que init-methodSpring utilise une méthode d'initialisation.
  2. Si vous avez une @PostConstructméthode, elle sera appelée avant les méthodes d'initialisation.
  3. Si votre bean implémente InitializingBean et substitue afterPropertiesSet, first @PostConstructest appelé, puis afterPropertiesSetet ensuite init-method.

Pour plus d'informations, vous pouvez consulter la documentation de référence de Spring .

Avant les spécifications JSR 250, l'utilisation de la méthode init en xml était la méthode préférée, car elle dissocie les classes Java (beans) de toutes les classes / annotations spécifiques au printemps. alors l'utilisation de la méthode init a été préférée.Pendant la méthode de création, vous pouvez spécifier la méthode à appeler comme méthode d'initialisation.

Désormais, avec l'introduction des spécifications JSR 250 dans Java EE et le support Spring de ces annotations, la dépendance au framework Spring a été réduite dans une certaine mesure.

Mais je dois admettre que l'ajout de ces éléments augmente la lisibilité du code.Il y a donc des avantages et des inconvénients dans les deux approches.


23
Si un bean utilise plus d'une de ces méthodes et se fie à l'ordre d'initialisation, il sera horriblement complexe et impossible à maintenir.
Donal Fellows

2
@Donal Tout à fait vrai. Fournissait simplement des informations sur la façon dont cela fonctionne.
Aravind A

1
Il y a une différence importante: vous devez configurer spécifiquement Spring pour traiter les annotations afin que @PostConstruct fonctionne: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, mais vous devez le savoir si vous prévoyez de passer des examens de certification;)
S.Klechkovski

@DonalFellows - Pouvez-vous préciser votre réponse? Je veux dire les difficultés rencontrées si un bean repose sur l'ordre d'initialisation. En fait, je veux savoir lequel est le meilleur. PostConstruct ou Bean (initMethod = "init") pour effectuer des opérations d'initialisation à partir d'un bean avant qu'il ne réponde aux requêtes?
Ayaskant

19

Il n'y a pas de réelle différence. Cela dépend de la façon dont vous préférez configurer votre système, et c'est une question de choix personnel. Moi-même, je préfère utiliser des @PostConstructannotations pour mon propre code (car le bean n'est correctement configuré qu'après l'appel de la méthode) et je l'utilise init-methodlors de l'instanciation de beans à partir de bibliothèques non compatibles Spring ( je ne peux pas y appliquer d'annotations, bien sûr!) mais je peux tout à fait comprendre les gens qui veulent tout faire d'une manière ou d'une autre.



3

Comme vous pouvez le voir dans le diagramme ci-dessous du rappel du cycle de vie de la création de bean .

Rappel du cycle de vie de création de haricots

Cette 3 étape se produit dans le rappel du cycle de vie de la création du bean:

  1. Il est mentionné qu'il @PostConstructsera appelé.
  2. Si InitializingBeanest implémenté, alors afterPropertiesSet()sera appelé.
  3. Si la définition du bean contient init-methodou @Bean(initmethod="..")alors elle appelle la méthode init.

Ce diagramme est tiré de Pro Spring 5: Un guide détaillé sur Spring Framework et ses outils


3

Il peut y avoir une différence entre @PostConstructet init-methodcar @PostConstructest géré dans la postProcessAfterInitializationphase d'initialisation du bean ( AbstractAutowireCapableBeanFactory.initializeBean()méthode) par CommonAnnotationBeanPostProcessor, tandis que la initméthode est appelée après la fin de la postProcessBeforeInitializationphase (et, pour cette question, avant le début de la postProcessAfterInitializationphase).
EDIT : Donc, la séquence est: 1) postProcessBeforeInitializationphase, 2) initméthode est appelée, 3) postProcessAfterInitializationphase, qui appelle la @PostConstructméthode

(En remarque, une déclaration de la réponse acceptée

@PostConstruct, init-method sont des BeanPostProcessors

n'est pas tout à fait correct: @PostConstructest géré par une méthode BeanPostProcessor, initne l'est pas.)

Il y aura une différence si certains (potentiellement personnalisés) BeanPostProcessor, qui sont configurés avec ( Ordered.getOrder()) pour être exécutés après CommonAnnotationBeanPostProcessor, font quelque chose de sérieux dans leur postProcessBeforeInitializationméthode.
Il n'y a aucune différence avec la configuration par défaut de Spring BeanPostProcessorscar tous ceux BeanPostProcessorsqui sont configurés pour être exécutés après CommonAnnotationBeanPostProcessor, ne font rien dans la postProcessBeforeInitializationméthode.

En conclusion, la réponse acceptée et les similaires sont justes ... dans 99% des cas, et ce post est juste pour rendre hommage à un concept "le diable est dans les détails"


Salut! Ceci est déroutant, si PostConstruct s'exécute avant la méthode init, comment est-il géré par la postProcessAfterInitialization si la méthode init s'exécute après postProcessBeforeInitialization et avant postProcessAfterInitialization ???
Maxrunner

@Maxrunner, désolé pour la confusion et merci beaucoup de l'avoir fait savoir! En fait, je n'ai jamais voulu dire que PostConstruct s'exécute avant la méthode init. Quoi qu'il en soit, j'ai mis à jour ma réponse avec quelques clarifications
igor.zh

2

Code complet ici: https://github.com/wkaczurba/so8519187 ( spring-boot )

Utilisation des annotations:

@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
    }
}

Nous obtient:

Actualisation de org.springframework.context ...

MyComponent in constructor: [null]
MyComponent in postConstruct: [Magic]
MyComponent in afterPropertiesSet: [Magic]
...

Enregistrement de beans pour l'exposition JMX au démarrage
DémoApplication démarrée en 0,561 seconde (JVM en cours d'exécution pour 1.011)
Fermeture de org.springframework.context .. . Annulation de l’enregistrement des beans exposés à JMX lors de l’arrêt


MyComponent in preDestroy: [Magic]

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.