Spring 5 Source Parsing - 1: Start with the Start Container

Keywords: Java Spring github

Start with the startup container

The simplest code to start spring is as follows:

@Configuration
@ComponentScan
public class AppConfig {
}

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AppConfig.class);
        context.close();
    }
}

Let's first take a look at the UML diagram of the AnnotationConfigApplicationContext class and make an impression.

Open Annotation Config Application Context (AppConfig. class); method to view 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();
}

This constructor allows us to pass in one or more class objects. The class object can be either annotated by @Configuration or a plain Java class.

Parametric constructor calls parametric constructor, point open source code:

public AnnotationConfigApplicationContext() {
    //Implicitly call the parent class constructor to initialize the beanFactory, which is implemented as DefaultListableBeanFactory
    super(); // This code is added by the author to facilitate location to the super method.

    //Create Annotated Bean Definition Reader,
    //Register annotations to the incoming Bean Definition Registry when created to configure the Bean Definition of the processors concerned
    this.reader = new AnnotatedBeanDefinitionReader(this);

    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

When initializing a subclass, the parent class will be initialized first, and the parent class parametric constructor will be called by default. Annotation Config Application Context inherits Generic Application Context. In the parametric constructor of Generic Application Context, the concrete implementation class DefaultListableBeanFactory of BeanFactory is created. BeanFactory in spring is instantiated here and is implemented by default using Default Listable BeanFactory.

public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

Two objects are also created in the constructor of Annotation Config Application Context: Annotated Bean Definition Reader and ClassPathBean Definition Scanner.

Starting with the role of scanner, by looking at the source code, you can see that this scanner is only used when you manually call some methods of Annotation Config Application Context (you can also find that spring does not use this scanner to scan packages for beans by exploring the source code later).

Create the AnnotatedBeanDefinitionReader object. spring passed this as a parameter to the constructor when it created reader. That is to say, the reader object contains a this object, the AnnotationConfigApplicationContext object. Annotation Config Application Context implements the BeanDefinition Registry interface. Open this. reader = new Annotated Bean Definition Reader (this); source code:

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

Get Environment from the incoming BeanDefinitionRegistry object, the AnnotationConfigApplicationContext object (sharing the same Environment), and then call another constructor. Point Open Source:

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry 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);
    //Register annotation configuration-related processors in BeanDefinition Registry
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

In this constructor, a very important method, AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry), is executed; as the name implies, spring registers processors related to annotation configuration through this method. Point Open Source:

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}
//Open source again
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        //org.springframework.context.annotation.internalConfigurationAnnotationProcessor - ConfigurationClassPostProcessor.class
        //This class is very important. It is a Bean Definition Registry Post Processor.
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}
  1. This method retrieves the DefaultListableBeanFactory object from the incoming BeanDefinitionRegistry object, that is, the AnnotationConfigApplicationContext object.
  2. Set properties for the obtained DefaultListableBeanFactory object
  3. Register BeanDefinition in DefaultListableBeanFactory objects, registering BeanDefinition in some Spring built-in PostProcessor (the next part of the introduction on BeanDefinition). Note that at this point, only the BeanDefinition is registered, and no bean s are instantiated. By default, after executing this method, the BeanDefinition registered in the spring container is:

Source Learning Notes: https://github.com/shenjianen...

Welcome to pay attention to the public number:

Posted by Xurion on Sun, 06 Oct 2019 06:25:06 -0700