[JAVA] [Printemps] Cycle de vie du haricot-de la génération à la destruction-

Aperçu

Cet article résume le cycle de vie du haricot. C'est une histoire plutôt interne. Nous partirons du principe que vous connaissez les mots-clés suivants.

En passant, j'ai passé l'examen Spring Professional v5.0 sponsorisé par pivotal l'autre jour, c'est donc un résumé de ce que j'ai appris à ce moment-là.

Cycle de vie du haricot

Le cycle de vie d'un haricot est à peu près divisé en trois.

  1. Phase d’initialisation
  2. Phase d'utilisation
  3. Phase de fin

Phase d'initialisation

Principalement dans cette phase

--Lire / réécrire la définition du bean

tenir. Cette phase est la plus complexe. Le flux général est comme ça

bean-lifecycle.001.jpeg

Regardons de plus près.

Lire la définition du bean

Tout d'abord, les informations requises pour générer le bean sont lues.

--Java Config avec @ Configuration --Classes avec @ Component, @ Controller, @ RestController, @ Service, @ Repository --Fichier XML avec définition de bean

Une liste d'informations de définition de bean est créée sur la base des informations lues ici. (L'entité est BeanDefinition ) Carte de l'objet?) La classe d'implémentation du bean, la portée, les beans dépendants, les champs, etc. sont écrits dans la liste d'informations de définition du bean.

Class Name Scope Depends on Property ...
com.example.hoge.AImpl a Singleton b url=${url} ...
com.example.fuga.BImpl b Prototype c age=10 ...
com.example.piyo.CImpl c Singleton ...

Réécrire la définition du bean

Ici, les informations de définition du bean sont réécrites. C'est une image que la liste d'informations de définition de Bean créée à l'étape précédente est modifiée. Par exemple, le processus d'incorporation d'une valeur de propriété dans un espace réservé déclaré avec «@ Value» est effectué ici.

AImpl.java


@Component("a")
public class AImpl implements A {

    @Value("${url}")
    private String url;
}

application.properties


url=http://www.sample.com

En fait, BeanDefinition est modifié en fonction de la valeur de propriété injectée par @ Value. BeanFactoryPostProcessor réalise la réécriture des informations de définition du bean. factory / config / BeanFactoryPostProcessor.java). Le traitement est effectué par la classe qui implémente l'interface BeanFactoryPostProcessor.

public interface BeanFactoryPostProcessor {
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory);
}

PropertySourcesPlaceholderConfigurer qui implémente BeanFactoryPostProcessor pour le processus d'incorporation des valeurs de propriété avec @ Value /springframework/context/support/PropertySourcesPlaceholderConfigurer.java) La classe est responsable. (Reportez-vous au lien pour un traitement détaillé) D'ailleurs, lors de l'utilisation de @ Value, il est nécessaire de définir un bean qui renvoie PropertySourcesPlaceholderConfigurer. (Il semble qu'il n'est pas nécessaire de le définir explicitement s'il s'agit de Spring Boot et Spring 4.3 ou version ultérieure) Ce bean doit être défini dans une méthode statique car Spring l'exécute avant la création du bean.

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

Ceci termine la génération des informations de définition de bean. En fait, le bean n'a pas encore été généré. Les haricots sont générés à partir de la phase suivante.

Génération de haricots et DI

À ce stade, un bean est finalement créé et DI (Dependency Injection) est exécuté. DI est effectué dans l'ordre suivant.

  1. Injection de constructeur
  2. Injection sur le terrain
  3. Injection de poseur

Processus d'initialisation après la génération du bean

Le traitement d'initialisation est effectué après la génération du bean. En tant que caractéristique du traitement qui peut être effectué ici, le traitement d'initialisation peut être effectué à l'aide du Bean généré. Par exemple, le traitement de la méthode avec «@ PostConstruct» est effectué à ce stade. Dans la méthode avec @ PostConstruct, vous pouvez écrire le processus d'initialisation en utilisant le champ injecté.

@Component
public class HogeServiceImpl implements HogeService {

    private final Fuga fuga;

    @Autowired
    public HogeServiceImpl(Fuga fuga) {
        this.fuga = fuga;
    }

    //Appelé après la fin de DI
    //La valeur de retour doit être vide, pas d'argument
    @PostConstruct
    public void populateCache() {
        ...
    }
}

Le prétraitement et le post-traitement peuvent être insérés avant et après le traitement d'initialisation de cette étape. Ce processus est BeanPostProcessor La classe qui implémente l'interface le fait.

public interface BeanPostProcessor {
    //Prétraitement
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    //Post-traitement
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

Phase d'utilisation

C'est la phase dans laquelle le haricot est réellement utilisé.

ApplicationContext context = SpringApplication.run(AppConfig.class);
HogeService service = context.getBean("hogeService", HogeService.class); //Obtenez Bean
service.do(); //Utilisation de haricots

Phase de fin

C'est la phase dans laquelle le conteneur DI est détruit.

Traitement avant élimination

Le traitement est effectué avant de détruire le conteneur DI. Les méthodes avec «@ PreDestroy» ajoutée sont traitées à ce stade.

@Component
public class HogeServiceImpl implements HogeService {

    //Appelé avant la destruction du conteneur DI
    //La valeur de retour doit être vide, pas d'argument
    @PreDestroy
    public void clearCache() {
        ...
    }
}

Jeter le contenant DI

Lorsque la méthode close de ConfigurableApplicationContext est appelée Le conteneur DI est détruit.

context.close();

S'il est généré par SpringApplication.run (), il s'accrochera à l'arrêt de la JVM et le conteneur DI sera détruit.

ConfigurableApplicationContext context = SpringApplication.run(AppConfig.class);
//ShutdownHook est enregistré dans la JVM

Matériel de référence

Recommended Posts

[Printemps] Cycle de vie du haricot-de la génération à la destruction-
Cycle de vie du haricot de printemps