编程知识 cdmana.com

Spring IOC loading process

spring The most important concept in English is IOC and AOP, however IOC Overall, there are two most important , One is to create Bean Containers , One is initialization Bean.

/**
* The configuration file 
*/
@Configuration
@ComponentSacn(basePackages = {""})
public class MainConfig{

}
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
//object  It's a self injected class , Please add your own 
Object obj = context.getBean(Object.class);

Take the above code as an example IOC Loading process of :

1、 Instantiate container :AnnotationConfigApplicationContext    

/**
* The following code snippet is AnnotationConfigApplicationContext.java
* A construction method of 
*/

// According to the parameter type, you can know , In fact, multiple annotatedClasses, But this situation is rare   
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { 
// Call parameterless constructor , The parent class will be called first GenericApplicationContext Constructor for  
// Initialization is in the constructor of the parent class DefaultListableBeanFactory, And assigned to beanFactory 
// In the constructor of this class , A reader is initialized :AnnotatedBeanDefinitionReader read, A scanner ClassPathBeanDefi nitionScanner scanner 
//scanner It's not very useful , It's just a manual call outside of us  .scan  Wait for the method to work , The normal way is not to use it scanner Object's  

this(); 

// Register the incoming class , Here are two situations , 
// Pass in the traditional configuration class  
// Pass in bean( Although no one usually does )
// I'll know when I see it spring Bring the traditional @Configuration The configuration class of is called FULL Configuration class , No @Configuration We call it Lite Configuration class  
// But let's take it here first @Configuration The configuration class of is called the traditional configuration class , Those without are called ordinary bean 

 register(annotatedClasses); 

// Refresh  
refresh()

}

        This is a constructor with arguments , Multiple configuration classes can be received , But in general , Only one configuration class is passed in .

        There are two cases for this configuration class , One is the traditional sense of the belt @Configuration Annotated configuration class , There is also a kind of no belt @Configuration, But with @Component,@Import,@ImportResource,@Service,@ComponentScan Class waiting for comment , stay Spring Internally we call the former Full Configuration class , Call the latter Lite Configuration class . Some places, too Lite The configuration class is called normal bean.

        this() Call the parameterless construction method of this class , The code is as follows :

// annotation bean Defined reader , The main function is to read annotated bean
private final AnnotatedBeanDefinitionReader reader;
// Scanner , It's just a manual call outside of us  .scan  Wait for the method to work , The normal way is not to use  Scanner  Object's 
private final ClassPathBeanDefinitonScanner scanner;

public AnnotationConfigApplicationContext(){
  // Will implicitly call the construction method of the parent class , initialization DefaultListableBeanFactory

  // Initialize a Bean Reader 
  this.reader = new AnnotatedBeanDefinitionReader(this);
  
  // Initializes a scanner , It's just a manual call outside of us  .scan  Wait for the method , The normal way is not to use it Scanner Object's 
  this.scanner = new ClassPathBeanDefinitionScanner(this);

}

    First of all, the nonparametric construction method is for the reader reader And scanners scanner It is instantiated ,reader The type is AnnotatedBeanDefinitionReader, It can be seen that this is a annotated Bean Define reader ,scanner The type is ClassPathBeanDefinitionScanner, It's just a manual call from outside .scan Method , Or the call parameter is String Construction method of , Only the package name that needs to be scanned will be used , Configuration classes passed in this way do not use this scanner Object's .AnnotationConfigApplicationContext Classes are inherited , Will implicitly call the construction method of the parent class .

2、 Example chemical plant :DefaultListableBeanFactory

/**
* Code inheritance relationships 
* The code structure 
*/
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
// As mentioned above 
}

//GenericApplicationContext  The code inheritance relationship of 
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;

	@Nullable
	private ResourceLoader resourceLoader;

	private boolean customClassLoader = false;

	private final AtomicBoolean refreshed = new AtomicBoolean();

    /**
	 * Create a new GenericApplicationContext.
	 * @see #registerBeanDefinition
	 * @see #refresh
	 */
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
}

    DefaultListableBeanFactory It's pretty important , It can be seen from the literal meaning that he is a Bean factory , For production and acquisition Bean Of .

3、 Instantiate create BeanDefinition Reader :AnnotatedBeanDefinitionReader

        I did two things :

           3.1 Register the built-in BeanPostProcessor

           3.2 Registration related BeanDefinition

       spring Initializing AnnotatedBeanDefinitionReader When , The following code

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry){
 this(registry,getOrCreateEnvironment(registry));
}

    here BeanDefinitionRegistry Of course it is AnnotationConfigApplicationContext An example of , Other construction methods of this class are directly called here :

public AnnotatedBeanDefinitionReader(BeanDefinitonRegistry registry,Environment environment){
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

}

    And then look at the last line , Get into registerAnnotationConfigProcessors(this.registry) Method :

/**
* Register all relevant annotation post processors in the given registry.
*  Register all relevant comments in the given registry, postprocessor 
* @param registry the registry to operate on
*/
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
	registerAnnotationConfigProcessors(registry, null);
}

    This is another facade method , Click in again , This method returns zero Set, But the upstream method does not receive the return value , So the return value of this method doesn't matter anymore , Of course, it's not important to assign this return value inside the method . Because this method has a lot of content , Just post the core method , The core method is to register Spring Built-in multiple Bean:

/**
*1. Determine if the container already exists ConfigurationClassPostProcessor Bean
*2. If it doesn't exist ( The first initialization certainly doesn't exist ), Just through RootBeanDefinition The construction method of is obtained ConfigurationClassPostProcessor Of BeanDefinition,
*RootBeanDefinition yes BeanDefinition Subclasses of 
*3. perform registerPostProcessor Method ,registerPostProcessor Inside the method is registration Bean, Of course, register others here Bean It's the same process .
**/
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

    BeanDefinition( Interface ) explain : Inherit upward BeanMetadataElement Interface (BeanDefinition Metadata , Return to the Bean The source of the )、AttributeAccessories Interface ( Provide right Bean The ability to manipulate properties ), There are many implementation classes down there , The structure is as follows: :

BeanDefinition Is used to describe Bean Of , It contains information about Bean A series of information , such as Bean Scope of action ,Bean The corresponding Class, Lazy loading , Dead or not Primary wait , This BeanDefinition It's also very important .

/**
*registerPostProcessor Method is BeanDefinition Set up a role,ROLE_INFRASTRUCTURE Representative is spring Inside , Not users 
* Defined , And then it calls again registerBeanDefinition Method , Click in , It's an interface , There's no way to just click in , The first thing to know is registry What is an implementation class , Here is DefaultListableBeanFactory
*
**/
private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
}

    Click in registerBeanDefinition Method , The core code is the following two lines of code :

//beanDefinitionMap yes Map<String, BeanDefinition>
// Here is the beanName As key,ScopedProxyMode As Value, Put it in map in 
this.beanDefinitionMap.put(beanName, beanDefinition);
//beanDefinitionNames It's just one. List<String>, Here is the beanName Put it in list Go inside 
this.beanDefinitionNames.add(beanName);

You can see it here DefaultListableBeanFactory That's what we call a container , There's... In it BeanDefinitionMap,BeanDefinitionNames,BeanDefinitionMap It's just one. hashMap,beanName As key,BeanDefinition As Value,beanDefinitionNames It's a collection , There is... In it beanName.(DefaultListableBeanFactory Medium BeanDefinitionMap,beanDefinitionNames It's pretty important , We often use , If you see it , It's better to know what data is stored in it at the first time .) This is just registration , It can be simply understood as putting some raw materials into the factory , The factory hasn't really produced yet . This has been described above , There will be a series of several registrations bean, The most important of all ( Not one of them. ) Namely BeanDefinitionRegistryPostProcessor Bean.ConfigurationClassPostProcessor Realization BeanDefinitionRegistryPostProcessor Interface ,BeanDefinitionRegistryPostProcessor The interface has expanded again BeanFactoryPostProcessor Interface ,BeanFactoryPostProcessor yes Spring One of the extension points ,ConfigurationClassPostProcessor yes Spring An extremely important class . The inheritance relationship between the above classes is :     

  In addition to registration ConfigurationClassPostProcessor, And registered other Bean, other Bean Other interfaces are implemented as well , such as BeanPostProcess etc. .BeanPostProcessor So is the interface Spring One of the extension points . thus , Instantiation AnnotatedBeanDefinitionReader Analysis complete .

4、 establish BeanDefinition Scanner :ClassPathBeanDefinitionScanner

        Because the normal way of use is not to use AnnotationConfigApplicationContext Inside scanner Of , there scanner Just so the programmer can call it manually AnnotationConfigApplicationContext Object's scan Method . This step can be omitted .

5、 The registration configuration class is BeanDefinition:register(annotatedClasses)

    The instantiation container is analyzed 、 Example chemical plant 、 Instantiation BeanDefinition Reader , The next analysis register(annotatedClasses) Method .

    ------- To be continued -------

6、refresh()

    6-5invokeBeanFactoryPostProcessors(beanFactory)

    6-11finishBeanFactoryLnitialization(beanFactory)

版权声明
本文为[Li Shengpeng]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/01/20210131224824874Q.html

Scroll to Top