Spring 5 Source Resolution 2-register Method Register Configuration Class

The last time I talked about this() method, let's look at register (annotated Classes); method.

// New Annotation Config Application Context (AppConfig. class); source code
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    //Call the default parameterless constructor, which has a lot of initialization logic
    this();

    //Register the incoming Class, either with @Configuration annotation or without @Configuration annotation
    //How to register? Delegated to the org. spring framework. context. annotation. AnnotatedBeanDefinitionReader. register method for registration
    // Input Class generates BeanDefinition, and then registers to BeanDefinition Registry
    register(annotatedClasses);

    //Refresh Container Context
    refresh();
}

Register (annotated Classes) method

Register (annotated Classes); the method actually calls reader's doRegisterBean (annotated Class, null, null); the method.

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    //Generate AnnotatedGenericBeanDefinition based on the incoming Class object.
    // AnnotatedGenericBeanDefinition is an implementation class of BeanDefinition
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    //Judge whether parsing needs to be skipped based on the @Conditional annotation
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    abd.setInstanceSupplier(instanceSupplier);
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

    //Resolve whether Class < T > annotated Class has a common annotation: @Lazy, @Primary, @DependsOn, @Role, @Description
    // And put the solution in Annotated Bean Definition
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

    //Class <? Extends Annotation >[] qualifiers are passed in through method calls
    // The last step is to parse whether there are annotations in Class. This step is passed in by the caller as a parameter.
    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 {
                //org.springframework.beans.factory.support.AbstractBeanDefinition.qualifiers
                //Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>();
                //Put it directly into map
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
        customizer.customize(abd);
    }

    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);

    //After converting the Class < T> annotated Class to BeanDefinition, registerBeanDefinition is performed by encapsulating it as a BeanDefinitionHolder object.
    //There is a Bean Definition Registry registry in Annotated Bean Definition Reader that is passed in through the construction method
    //new AnnotationConfigApplicationContext(AppConfig.class); AnnotationConfigApplicationContext extends GenericApplicationContext
    // The GenericApplicationContext class implements BeanDefinitionRegistry, which is AnnotationConfigApplicationContext
    // The GenericApplicationContext class implements the BeanDefinitionRegistry interface internally through DefaultListableBeanFactory
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
  1. Create AnnotatedGenericBeanDefinition based on the incoming class object, AnnotatedGenericBeanDefinition is an implementation class of BeanDefinition.
  2. Based on the @Conditional annotation, to determine whether parsing needs to be skipped, it is obvious that it is not needed here, return false, and the code continues to execute downward.
  3. Set the properties of BeanDefinition based on the incoming parameters
  4. Resolve whether the incoming class object has a generic annotation (@Lazy,@Primary,@DependsOn,@Role,@Description), and put the result into Annotated Bean Definition.
  5. Determine if there is an incoming Class <? Extends Annotation >[] qualifiers parameter, and if it is not null, set the incoming qualifiers parameter to BeanDefinition. Note that step 4 parses whether there are generic annotations in the class. The annotations for this judgment are passed in manually by the caller.
  6. After converting the incoming class object into BeanDefinition, the BeanDefinition is encapsulated in BeanDefinition Holder (for convenience of parameter transfer), and then BeanDefinition ReaderUtils. RegiserBeanDefinition (definition Holder, this. registry) is called to register the BeanDefinition.
  7. The. register object passed in when the registerBeanDefinition method is called is an attribute of AnnotatedBeanDefinitionReader, which is initialized in the constructor. This. register object is actually the AnnotationConfigApplicationContext object. AnnotationConfigApplicationContext inherits GenericApplicationContext, and the GenericApplicationContext class implements the BeanDefinitionRegistry interface. In the Generic ApplicationContext class, the member variable bean Factory is delegated to implement the BeanDefinitionRegistry interface.
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;
  1. Let's look at the registerBeanDefinition method. Mainly through registry. registerBeanDefinition (bean Name, definition Holder. getBeanDefinition ()); the method registers BeanDefinition into DefaultListableBeanFactory, that is, spring container.
public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

The so-called Registered BeanDefinition is simply understood as placing BeanDefinition in the BeanDefinition Map of the DefaultListableBeanFactory object.

//Org. spring framework. beans. factory. support. DefaultListableBeanFactory # registerBeanDefinition method source code
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        } catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }

    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    //Existing Definition must be null the first time you come in
    if (existingDefinition != null) {
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        } else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean '" + beanName +
                        "' with a framework-generated bean definition: replacing [" +
                        existingDefinition + "] with [" + beanDefinition + "]");
            }
        } else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        } else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        this.beanDefinitionMap.put(beanName, beanDefinition);
    } else {
        if (hasBeanCreationStarted()) {
            // Cannot modify startup-time collection elements anymore (for stable iteration)
            synchronized (this.beanDefinitionMap) {
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        } else {
            // Still in startup registration phase
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

After running register (annotated classes); after the method, there are no instantiated bean s in the spring container, but only some BeanDefinition s registered. (Registered are some postProcessor s inside Spring and AppConfig classes passed in by our code.)

Source Learning Notes GITHUB Warehouse Address: https://github.com/shenjianen...

Welcome to the public number: Coder Xiaohei

Keywords: Java Spring github Attribute

Added by harsh00008 on Fri, 04 Oct 2019 04:21:47 +0300