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à.
Le cycle de vie d'un haricot est à peu près divisé en trois.
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
Regardons de plus près.
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 | ... |
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.
À ce stade, un bean est finalement créé et DI (Dependency Injection) est exécuté. DI est effectué dans l'ordre suivant.
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;
}
}
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
C'est la phase dans laquelle le conteneur DI est détruit.
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() {
...
}
}
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