A preface.

In the previous article in the Spring source series, Container Startup (part 1), we parsed the constructor. This article continues with the second approach

public AnnotationConfigApplicationContext(Class
       ... componentClasses) {
    this(a);// 2. Register related information based on the configuration class
    register(componentClasses);
    refresh();
}
Copy the code

Register () method parsing

After the no-argument constructor is parsed, the constructor next executes the second method:

// In our example, componentClasses is the config.class we passed in
public void register(Class
       ... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    / / is actually entrusted to AnnotatedBeanDefinitionReader classes to register
    this.reader.register(componentClasses);
}
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- line -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
public void register(Class
       ... componentClasses) {
    for(Class<? > componentClass : componentClasses) {// Delegate to the internal registerBean methodregisterBean(componentClass); }}/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- line -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
public void registerBean(Class
        beanClass) {
	// Finally see the true face of Lushan! Delegate to the internal doRegisterBean() method
    doRegisterBean(beanClass, null.null.null.null);
}
Copy the code

2.1 doRegisterBean() source code parsing

The source code for doRegisterBean() is important because in Spring, all beans are injected into the container through this method! Source code as follows (high energy warning):

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
        @Nullable BeanDefinitionCustomizer[] customizers) {

    / / according to class to generate a beanDefinition, concrete type is AnnotatedGenericBeanDefinition
    // In the current scenario, beanClass is the config.class passed in
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    // Determine if there are conditional annotations in the current configuration class based on the condition parser in the previous reader, and if so, determine if the registration needs to be skipped temporarily.
    // Remember the conditional parser used during Scanner initialization? This is where it works!
    // In the current scenario, since the Config class is not configured with any conditional, there is no need to skip registration
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    // Set the Supplier function
    In the current scenario, supplier is null
    abd.setInstanceSupplier(supplier);
    
    // Parse bd ScopeMetadata. When the reader is initialized scopeMetadataResolver initialize the default AnnotationScopeMetadataResolver type
    // If there is an @scope annotation on the class, scopeName and proxyNode are resolved
    // scopeName (scope: singleton or prototype?)
    // proxyNode (JDK or Cglib?)
    // @scope is also very important!! However, the explanation will not be expanded here, and will be explained in separate chapters
    // In the current scenario, Config does not have the @scope annotation, so Config here will default to singletons and no proxy technology.
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    
    // Set the scope of beanDefinition
    // The current scenario is singleton
    abd.setScope(scopeMetadata.getScopeName());
    
    // The name of the generated bean
    / / when the reader is initialized, the default beanName generator for AnnotationBeanNameGenerator.
    // We can also customize beanName generators ourselves by inheriting BeanNameGenerator if necessary. In general, the default is fine.
    // The default beanName generation strategy is lowercase.
    // In the current scenario, the beanName of the Config class is: ConfigString beanName = (name ! =null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    // Important!! Handles public annotations such as @lazy, @Order, @Priority, @dependson.
    // The function of these annotations is very simple and I won't go into detail here.
    // In the current scenario, the Config class does not have these annotations.
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

    // If there are other qualified annotations, set them
    // The Config class is obviously absent in the current scenario
    if(qualifiers ! =null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(newAutowireCandidateQualifier(qualifier)); }}}// BeanDefinitionCustomizer calls back to beanDefinition
    // In the current scenario, no callback processing is required
    if(customizers ! =null) {
        for(BeanDefinitionCustomizer customizer : customizers) { customizer.customize(abd); }}// Encapsulate beanDefinition and beanName as BDH
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    
    // Important!! Here, scopeMetadata is used to determine whether beanDefinition needs to be brokered. If necessary, the beanDefinition of the proxy class is generated and assigned to BDH!
    // In this scenario, no proxy is required, so the BDH does not change.
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    
    // Register the beanDefinition represented by BDH
    In this scenario, the BDS represented by the Config class are registered. After successful registration, there are seven BDS in the factory (remember the six BDS registered earlier).
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
Copy the code

3. To summarize

At this point, the config. class class has been wrapped as a BeanDefinition and added to the container. Next, we’ll break down the most important step!