Comment fonctionne exactement le Spring BeanPostProcessor?

94

J'étudie pour la certification Spring Core et j'ai des doutes sur la façon dont Spring gère le cycle de vie des beans et en particulier sur le post-processeur de haricots .

J'ai donc ce schéma:

entrez la description de l'image ici

Ce que cela signifie est assez clair pour moi:

Les étapes suivantes ont lieu dans la phase de définition des définitions de bean :

  • Les classes @Configuration sont traitées et / ou les @Components sont analysés et / ou les fichiers XML sont analysés.

  • Définitions de bean ajoutées à BeanFactory (chacune indexée sous son id)

  • BeanFactoryPostProcessor spéciaux appelés , il peut modifier la définition de n'importe quel bean (par exemple pour les remplacements de valeurs de propriété-espace réservé).

Ensuite, les étapes suivantes ont lieu dans la phase de création des beans :

  • Chaque bean est instancié avec empressement par défaut (créé dans le bon ordre avec ses dépendances injectées).

  • Après l'injection de dépendances, chaque bean passe par une phase de post-traitement au cours de laquelle une configuration et une initialisation supplémentaires peuvent se produire.

  • Après le post-traitement, le bean est entièrement initialisé et prêt à être utilisé (suivi par son identifiant jusqu'à ce que le contexte soit détruit)

Ok, c'est assez clair pour moi et je sais aussi qu'il existe deux types de post-processeurs de haricots qui sont:

  • Initialiseurs: initialisez le bean si vous y êtes invité (par exemple @PostConstruct).

  • et tout le reste: qui permet une configuration supplémentaire et qui peut s'exécuter avant ou après l'étape d'initialisation

Et je poste cette diapositive:

entrez la description de l'image ici

Il est donc très clair pour moi ce que font les initialiseurs bean post processors (ce sont les méthodes annotées avec l' annotation @PostContruct et qui sont automatiquement appelées immédiatement après les méthodes setter (donc après l'injection de dépendance), et je sais que je peux utiliser pour effectuer un certain lot d'initialisation (comme remplir un cache comme dans l'exemple précédent).

Mais que représente exactement l'autre post-processeur de haricots? Que voulons-nous dire quand nous disons que ces étapes sont effectuées avant ou après la phase d'initialisation ?

Ainsi mes beans sont instanciés et ses dépendances sont injectées, donc la phase d'initialisation est terminée (par l'exécution d'une méthode annotée @PostContruct ). Qu'entend-on par dire qu'un Bean Post Processor est utilisé avant la phase d'initialisation? Cela signifie que cela se produit avant l' exécution de la méthode annotée @PostContruct ? Cela signifie-t-il que cela pourrait se produire avant l'injection de dépendances (avant que les méthodes setter soient appelées)?

Et que voulons-nous dire exactement quand nous disons qu'elle est effectuée après l'étape d'initialisation . Cela signifie qu'il se produit après cela l'exécution d'une méthode annotée @PostContruct , ou quoi?

Je peux facilement comprendre pourquoi j'ai besoin d'une méthode annotée @PostContruct mais je ne peux pas trouver d'exemple typique de l'autre type de post-processeur de haricots, pouvez-vous me montrer un exemple typique de quand sont utilisés?

AndreaNobili
la source
Je suis sûr que vous ne devriez pas partager les images des diapositives :)
Reg
@Reg De quel cours / présentation exacte proviennent ces images?
Malvon
@Malvon Cela provenait de l'édition précédente du cours de base officiel du printemps de Pivotal. ET BTW - Si vous vous préparez à l'examen, ignorez tout avec XML :)
Reg
@Reg Existe-t-il un moyen d'acheter le cours sans participer réellement aux cours de formation?
Malvon le
Je me demande ce qui se passe dans cette partie violette du diagramme «Post-process Bean Definitions»?
Akshay Hiremath le

Réponses:

48

Spring doc explique les BPP sous Personnalisation des beans à l'aide de BeanPostProcessor . Les beans BPP sont un type spécial de beans qui sont créés avant les autres beans et interagissent avec les beans nouvellement créés. Avec cette construction, Spring vous donne les moyens de vous connecter et de personnaliser le comportement du cycle de vie simplement en implémentant un BeanPostProcessorvous - même.

Avoir un BPP personnalisé comme

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}

serait appelé et afficherait la classe et le nom du bean pour chaque bean créé.

Pour comprendre comment la méthode s'adapte au cycle de vie du bean, et quand exactement la méthode est appelée, consultez la documentation

postProcessBeforeInitialization (Object bean, String beanName) Appliquez ce BeanPostProcessor à la nouvelle instance de bean donnée avant tout rappel d'initialisation du bean (comme afterPropertiesSet d'InitializingBean ou une méthode init personnalisée).

postProcessAfterInitialization (Object bean, String beanName) Appliquez ce BeanPostProcessor à la nouvelle instance de bean donnée après les rappels d'initialisation du bean (comme afterPropertiesSet d'InitializingBean ou une méthode init personnalisée).

L'important est aussi que

Le bean sera déjà rempli avec des valeurs de propriété.

Pour ce qui concerne la relation avec la @PostConstructnote que cette annotation est un moyen pratique de déclarer une postProcessAfterInitializationméthode, et Spring en prend conscience lorsque vous enregistrez CommonAnnotationBeanPostProcessorou spécifiez le <context:annotation-config />fichier de configuration du bean. L' @PostConstructexécution de la méthode avant ou après une autre postProcessAfterInitializationdépend de la orderpropriété

Vous pouvez configurer plusieurs instances de BeanPostProcessor et vous pouvez contrôler l'ordre dans lequel ces BeanPostProcessor s'exécutent en définissant la propriété order.

Maître d'esclave
la source
30

L'exemple typique pour un post-processeur de bean est lorsque vous voulez envelopper le bean d'origine dans une instance de proxy, par exemple lorsque vous utilisez l' @Transactionalannotation.

Le post-processeur du bean recevra l'instance d'origine du bean, il peut appeler n'importe quelle méthode sur la cible, mais il peut également renvoyer l'instance réelle du bean qui devrait être liée dans le contexte de l'application, ce qui signifie qu'il peut en fait renvoyer n'importe quel objet qu'il veut. Le scénario typique lorsque cela est utile est lorsque le post-processeur de bean enveloppe la cible dans une instance de proxy. Toutes les invocations sur le bean lié dans le contexte de l'application passeront par le proxy, et le proxy peut alors effectuer un peu de magie avant et / ou après les invocations sur le bean cible, par exemple AOP ou gestion des transactions.

marthursson
la source
6
Félicitations pour un exemple réel!
raiks
merci d'avoir fourni un cas d'utilisation réel et pas seulement de la théorie
Amol Aggarwal
4

La différence est de BeanPostProcessorse connecter à l'initialisation du contexte, puis d'appeler postProcessBeforeInitializationet postProcessAfterInitializationpour tous les beans définis.

Mais @PostConstructest juste utilisé pour la classe spécifique que vous souhaitez personnaliser la création du bean après le constructeur ou la méthode set.

Tam Le
la source