Preface
This article mainly introduces the relevant content about the loading of Context when Spring starts. It is shared for your reference and learning. I won’t say much below, let’s take a look at the detailed introduction together.
Test source code download test-annotation.zip
There is the following code
@Componentpublic class HelloWorldService { @Value("${name:World}") private String name; public String getHelloMessage() { return "Hello " + this.name; }}@Configurationpublic class BootStrap { @Bean public static HelloWorldService helloService() { return new HelloWorldService(); } public static void main(String[] args) { InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); beanFactory.setInstantiationStrategy(instantiationStrategy); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(beanFactory); applicationContext.register(BootStrap.class); applicationContext.refresh(); HelloWorldService service = applicationContext.getBean(HelloWorldService.class); System.out.println(service.getHelloMessage()); applicationContext.close(); }} HelloWorldService.getHelloMessage method simply returns the value of name. BootStrap.main method uses AnnotationConfigApplicationContext to construct a context object. For the convenience of demonstration, the displayed declarations of DefaultListableBeanFactory and InstantiationStrategy instances. Get the reference of the bean through applicationContext.getBean() and call service.getHelloMessage() method.
The loading of the context mainly occurs in applicationContext.register method and applicationContext.refresh method.
The purpose of the applicationContext.register method is to generate a BeanDefinition object for the parameter (class annotated using @Configuration) and call DefaultListableBeanFactory.registerBeanDefinition to register the BeanDefinition into the DefaultListableBeanFactory.
The function of applicationContext.refresh() is more. The main function is to call the PostProcessor to generate the corresponding BeanDefinition object for the @Bean annotation method in the @Configuration class and register it in the DefaultListableBeanFactory. The second function is to traverse the BeanDefinition in the DefaultListableBeanFactory to generate the real object.
The detailed process of generating a BeanDefinition object for the @Bean annotation method in the @Configuration class is as follows
Step 1. Find the appropriate BeanDefinitionRegistryPostProcessor processor
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() { ... //Get the applicable BeanDefinitionRegistryPostProcessor bean name String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); ... //GetPostProcessor based on beanName, The beanName of the @Configuration annotation class is //org.springframework.context.annotation.internalConfigurationAnnotationProcessor //Implemented as org.springframework.context.annotation.ConfigurationClassPostProcessor ConfigurationClassPostProcessor postProcessor =beanFactory.getBean(postProcessorNames[0], BeanDefinitionRegistryPostProcessor.class)} Step 2: Generate ConfigurationClass object for @Configuration
//Use ConfigurationClassParser to parse the class annotated by @Configuration,
//Each @Configuration annotated class generates a ConfigurationClass object.
// ConfigurationClass.getBeanMethods() can obtain all methods in this class that use @Bean annotation.
//The @Bean annotation method is represented by the BeanMethod object
org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry registry) { ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); parser.parse(configCandidates); parser.validate(); this.reader.loadBeanDefinitions(parser.getConfigurationClasses());}Step 3. The @Bean annotation method generates a BeanDefinition and injects it into the DefaultListableBeanFactory
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass); beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(metadata.getMethodName()); //registry is an instance of DefaultListableBeanFactory this.registry.registerBeanDefinition(beanName, beanDefToRegister);}Call stack for this procedure:
Generate the call stack of the instance procedure according to BeanDefinition:
Summarize
The above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. If you have any questions, you can leave a message to communicate. Thank you for your support to Wulin.com.