Backend Development 15 min read

Deep Dive into Spring Framework Container Startup: Constructor, BeanFactory, Reader, and Scanner Initialization

This article walks through the Spring Framework container startup process, explaining how the AnnotationConfigApplicationContext constructor prepares the environment, registers readers and scanners, initializes the BeanFactory, sets up condition evaluators and post‑processors, and outlines the default filters used for component scanning.

Top Architect
Top Architect
Top Architect
Deep Dive into Spring Framework Container Startup: Constructor, BeanFactory, Reader, and Scanner Initialization

1. Introduction

The Spring family is huge, and mastering it requires focusing on its core, the Spring Framework. This article records a portion of the author's source‑code study, concentrating on how the Spring container scans beans during startup.

2. Learning Methodology

The author emphasizes hands‑on debugging of Spring source code, building the project locally, and using both XML, annotation, and Java‑Config entry points, which ultimately delegate to the same underlying container initialization.

3. Code Entry

The entry point of the application is shown below:

@Configuration
@ComponentScan("com.leon.funddatahouse")
public class Config {
}

public class MyApplication {
    public static void main(String[] args) {
        // annotation‑based configuration
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        // XML‑based configuration (commented out)
        // ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context.xml");
    }
}

The constructor performs three essential steps that constitute the whole Spring container startup.

4. Before Parsing

UML class diagrams of the container and BeanFactory are presented to illustrate their complex roles.

5. Source Code Analysis

5.1 Constructor Analysis

5.1.1 Initializing the BeanFactory

The no‑arg constructor of AnnotationConfigApplicationContext creates a DefaultListableBeanFactory inside the parent GenericApplicationContext :

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

5.1.2 Instantiating the Reader

The reader ( AnnotatedBeanDefinitionReader ) is created to assist bean definition registration. Its constructor registers the environment, a condition evaluator, and essential post‑processors:

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

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);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

5.1.2.1 ConditionEvaluator

The ConditionEvaluator delegates to an internal ConditionContextImpl that holds the registry, bean factory, environment, resource loader and class loader.

public ConditionEvaluator(@Nullable BeanDefinitionRegistry registry,
                         @Nullable Environment environment,
                         @Nullable ResourceLoader resourceLoader) {
    this.context = new ConditionContextImpl(registry, environment, resourceLoader);
}

public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
                           @Nullable Environment environment,
                           @Nullable ResourceLoader resourceLoader) {
    this.registry = registry;
    this.beanFactory = deduceBeanFactory(registry);
    this.environment = (environment != null ? environment : deduceEnvironment(registry));
    this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
    this.classLoader = deduceClassLoader(resourceLoader, this.beanFactory);
}

5.1.2.2 Registering Post‑Processors

The static method registerAnnotationConfigProcessors registers a set of built‑in post‑processors (e.g., ConfigurationClassPostProcessor , AutowiredAnnotationBeanPostProcessor , etc.) as bean definitions:

public static Set
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
beanDefs = new LinkedHashSet<>(8);
    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));
    }
    // ... similar registration for AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, etc.
    return beanDefs;
}

5.1.3 Instantiating the Scanner

The scanner ( ClassPathBeanDefinitionScanner ) is responsible for scanning classpath resources and applying default filters:

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
        Environment environment, @Nullable ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
    if (useDefaultFilters) {
        registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}

5.1.3.1 registerDefaultFilters()

The default filters include @Component , @ManagedBean , and @Named annotations, ensuring that classes annotated with these are considered candidates for bean definition creation.

protected void registerDefaultFilters() {
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            (Class
) ClassUtils.forName("javax.annotation.ManagedBean", cl), false));
    } catch (ClassNotFoundException ex) {}
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            (Class
) ClassUtils.forName("javax.inject.Named", cl), false));
    } catch (ClassNotFoundException ex) {}
}

6. Summary of the Default Constructor

The final constructor of AnnotationConfigApplicationContext simply calls the no‑arg constructor, registers the supplied component classes, and refreshes the context, encapsulating all the previously described initialization steps.

public AnnotationConfigApplicationContext(Class
... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

Overall, the article demonstrates that the first three lines of the entry point trigger a cascade of actions that set up the BeanFactory, Environment, ConditionEvaluator, and a suite of post‑processors, forming the backbone of Spring’s container startup.

At the end, the author includes promotional QR codes and links to related articles, encouraging readers to join a WeChat group for further architectural discussions.

backendJavaSpringdependency injectionBeanFactoryAnnotationConfigApplicationContext
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.