Foundation · Understand

From XML Beans to Modern Spring Configuration

Define one object graph with XML, @Configuration and @Bean, and component scanning—and see how every style produces bean-definition metadata for the same container.

Primary source: Spring Framework 6.2 Reference: Bean Overview

28 min

Lesson 2 of 14

1d streak

The Architectural Question

Without the XML-to-Java history, @Bean and @Component look like unrelated magic instead of alternative ways to describe object recipes.

What this guide proves

  • XML bean metadata
  • Java configuration
  • Component scanning

Configuration styles feed the same container

Spring configuration has changed shape, but its job has stayed stable: describe which objects the container should manage and how they depend on one another. XML, @Configuration classes, @Bean methods, and component scanning are metadata sources—not different containers.

Configuration sourceWhat it contributesGood fit
XML <bean>Explicit BeanDefinition metadata loaded from a resourceLegacy systems and externally visible wiring
@Bean methodA definition backed by a Java factory methodThird-party types and explicit construction
Component scanningDefinitions discovered from annotated application classesControllers, services, repositories, and adapters
Boot auto-configurationConditional definitions contributed by librariesSafe framework defaults that back off when replaced

XML made the object graph external and explicit

Early Spring applications commonly placed bean metadata in XML. The id named the recipe, the class selected the implementation, and constructor arguments or properties described dependencies. ClassPathXmlApplicationContext read the resource and populated the container.

application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
         https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="paymentGateway" class="example.StripePaymentGateway">
        <constructor-arg value="${stripe.api-key}" />
    </bean>

    <bean id="checkoutService" class="example.CheckoutService">
        <constructor-arg ref="paymentGateway" />
    </bean>
</beans>
LegacyApplication.java
try (var context =
         new ClassPathXmlApplicationContext("application-context.xml")) {
    CheckoutService service = context.getBean(CheckoutService.class);
    service.checkout(order);
}

Why interviewers still ask about XML

Many enterprise systems still contain XML configuration. More importantly, XML exposes the underlying model clearly: named bean definitions, implementation classes, constructor references, properties, scopes, and lifecycle methods.

Java configuration made the same recipes type-safe

@Configuration marks a class as a source of bean definitions. Each @Bean method is the Java equivalent of an XML <bean> element: the method name is normally the bean name, the return type is the exposed type, parameters are dependencies, and the method body constructs the object.

PaymentConfiguration.java
@Configuration
class PaymentConfiguration {

    @Bean
    PaymentGateway paymentGateway(PaymentProperties properties) {
        return new StripePaymentGateway(properties.apiKey());
    }

    @Bean
    CheckoutService checkoutService(PaymentGateway gateway) {
        return new CheckoutService(gateway);
    }
}

Architectural Boundary · Do Not Confuse

Concept A

XML <bean id="checkoutService">

Concept B

@Bean CheckoutService checkoutService(...)

Both register a recipe named checkoutService. They differ in authoring format and tooling, not in the fundamental container model.

Active Recall Checkpoint

Does calling an @Bean method always create a fresh Java object?

Hint: Consider who is invoking the method and the bean scope.

Show answer & explanation

Not when the container resolves the bean definition. For a singleton-scoped bean, the container returns the managed singleton. Direct calls and proxy behavior depend on whether the configuration class uses full or lite configuration semantics, so application code should request dependencies through injection.

Component scanning discovers application-owned definitions

Component scanning searches configured packages for stereotype annotations and registers a BeanDefinition for each candidate. @Component is the general stereotype; @Service, @Repository, and @Controller add architectural meaning and can enable specialized framework behavior.

CheckoutService.java
@Service
final class CheckoutService {
    private final PaymentGateway gateway;

    CheckoutService(PaymentGateway gateway) {
        this.gateway = gateway;
    }
}

Scanning does not create arbitrary objects

Scanning registers definitions for classes inside the scan boundary that match its filters. A missing bean is often a registration problem—wrong package, missing import, failed condition, or no definition—before it is an injection problem.

Trace every style into the BeanDefinition pipeline

  1. 01A metadata reader, configuration parser, or scanner discovers configuration.
  2. 02The container registers BeanDefinition recipes in a BeanDefinitionRegistry.
  3. 03BeanFactoryPostProcessor implementations may modify the recipes before ordinary beans exist.
  4. 04The BeanFactory instantiates beans and resolves dependencies from the registered definitions.
  5. 05BeanPostProcessor implementations observe or wrap bean instances around initialization.
  6. 06The ApplicationContext exposes the final managed object, which may be a proxy.

Active Recall Checkpoint

When NoSuchBeanDefinitionException occurs, what should you investigate first?

Show answer & explanation

Verify that a matching definition was registered: check XML resources, configuration imports, scan boundaries, bean names and types, profiles, and conditional configuration. Dependency resolution cannot select a bean that was never registered.

A strong interview summary

XML, @Bean methods, component scanning, and Boot auto-configuration are different sources of BeanDefinition metadata. The same Spring container consumes those definitions, resolves dependencies, manages lifecycle, and returns the resulting bean or proxy.

Working Implementation

Code Walkthrough

Load the same PaymentService graph with ClassPathXmlApplicationContext and AnnotationConfigApplicationContext, then compare the registered bean names and types.

XmlVsJavaConfigLab.java
package com.example.core;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

public class XmlVsJavaConfigLab {
    public record InventoryClient(String warehouseUrl) {}
    public record OrderProcessor(InventoryClient inventory) {}

    @Configuration
    // Hybrid migration support: @ImportResource("classpath:legacy-beans.xml")
    public static class ModernConfig {
        @Bean
        InventoryClient inventoryClient() {
            return new InventoryClient("https://warehouse-eu.internal/api/v2");
        }

        @Bean
        OrderProcessor orderProcessor(InventoryClient inventory) {
            return new OrderProcessor(inventory);
        }
    }

    public static void main(String[] args) {
        // Both XML <bean> tags and Java @Bean methods populate the exact same BeanDefinitionRegistry
        try (var context = new AnnotationConfigApplicationContext(ModernConfig.class)) {
            OrderProcessor processor = context.getBean(OrderProcessor.class);
            System.out.println("Warehouse configured: " + processor.inventory().warehouseUrl());
            System.out.println("Registered bean definition count: " + context.getBeanDefinitionNames().length);
        }
    }
}
XML <bean> and Java @Bean are alternative metadata sources for the same BeanDefinitionRegistry; the container engine is identical.
@Configuration classes provide compile-time type safety, refactoring support, and full IDE navigation that XML lacks.
In legacy enterprise migrations, @ImportResource bridges existing XML configurations into modern Spring Boot applications.

Synthesis & Production Verification

Deliberate Failure Condition

  1. Break: Mix XML, component scanning, and Java configuration without knowing which source owns a bean
  2. Observe: Duplicate names, surprising overrides, or NoSuchBeanDefinitionException at startup
  3. Repair: Trace configuration metadata to the BeanDefinition registry before debugging object creation.

Production Acceptance Criteria

  • Map an XML bean element to an equivalent @Bean method
  • Explain what component scanning registers
  • Choose explicit Java configuration for third-party objects and scanning for application components

Architectural & Technical Review

Core Interview Questions

Q01How is an XML bean element related to an @Bean method?Show answer

Both register bean-definition metadata. The XML id corresponds to the bean name, the class or factory method determines construction, and constructor references or method parameters describe dependencies. The authoring format differs; the container model does not.

Q02What does component scanning actually do?Show answer

It searches configured packages with type filters, finds candidate component classes, derives bean names and metadata, and registers BeanDefinition objects. Bean instances are created later by the container lifecycle.

Q03How would you diagnose NoSuchBeanDefinitionException?Show answer

First verify registration: inspect scan boundaries, configuration imports, XML resources, profiles, conditions, names, and exposed types. Only after confirming a definition exists should you investigate autowire candidate selection.

Production Pitfalls

Critical Anti-Patterns

  • Pitfall: Treating XML and annotations as different dependency-injection engines — They are metadata sources for the same BeanFactory and lifecycle pipeline.
  • Pitfall: Using scanning for third-party classes — Use an explicit @Bean factory method when you do not own or cannot annotate the class.

Primary Documentation & Specifications

Supplementary Module Resources