In large-scale enterprise Java applications, keeping all bean definitions inside a single configuration class quickly leads to bloated, unmaintainable code. Spring's @Import annotation provides an elegant solution by allowing developers to split bean configurations across focused, modular @Configuration classes and aggregate them cleanly into a central configuration hub.
How Aggregating Configuration Works
Instead of registering multiple configuration classes manually when initializing the container, you designate one primary or root configuration class and aggregate other specialized classes:
Modular Configuration Classes: Separate your beans logically into domain-specific modules (such as AppConfigA and AppConfigB).
Aggregation Hub: Annotate a root configuration class with @Import({AppConfigA.class, AppConfigB.class}) to consolidate the configurations.
Simplified Container Bootstrapping: Pass only the main configuration class to AnnotationConfigApplicationContext. Spring automatically discovers and loads all imported classes and their associated @Bean definitions.
Step-by-Step Implementation Flow
Define Feature Configs: Create individual configuration classes annotated with @Configuration, defining beans specific to their feature.
Create Main Config: Define a main aggregation class (e.g., AppConfig) and apply @Import passing an array of module configuration classes.
Initialize ApplicationContext: Instantiate the container with new AnnotationConfigApplicationContext(AppConfig.class).
Access Beans: Retrieve beans declared across any of the imported configuration classes seamlessly from the single context.
Major Architectural Benefits
Separation of Concerns: Keeps configuration files cohesive, lightweight, and focused on specific domains (e.g., database, security, or business logic).
Easier Unit & Integration Testing: Allows test suites to bootstrap only relevant configuration modules rather than the entire application graph.
Clean Maintenance: Adding, removing, or swapping modular features becomes as simple as updating an entry in the @Import array.
Recommended Next Videos
Continue your deep dive into Spring configuration and annotations with these tutorials from our channel:
@Bean(name = "customer") public Customer customer() { System.out.println( "In CustomerConfig employee() is called by the Spring container"); returnnew Customer("John"); }
Customer customer = (Customer) context.getBean("customer"); System.out.println("Got customer object from the ApplicationContext");
customer.customerDetails();
} }
Output
Oct 07, 2018 7:32:15 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f4da5c3: startup date [Sun Oct 07 07:32:15 IST 2018]; root of context hierarchy
In EmployeeConfig employee() is called by the Spring container
com.ram.core.Employee, Employee(String name) constructor is called, Peter
In CustomerConfig employee() is called by the Spring container
com.ram.core.Customer, Customer(String name) constructor is called, John
---------------------------------------
Got employee object from the ApplicationContext
Employee Name = Peter
---------------------------------------
Got customer object from the ApplicationContext
Customer Name = John
Mastering Spring JavaConfig with the @Import Annotation
As enterprise Spring applications grow in scale, consolidating all configuration beans into a monolithic class quickly creates technical debt and maintainability challenges. Spring provides the @Import annotation as the standard mechanism to organize, separate, and import modular @Configuration classes cleanly, keeping configuration files modular, focused, and test-friendly.
How @Import Simplifies Spring Configuration
The @Import annotation functions as the pure Java equivalent of the traditional <import resource="..."/> element in XML configuration:
Granular Configuration: Distinct domain layers (such as service configurations, persistence settings, or security filters) are isolated in separate classes marked with @Configuration.
Centralized Composition: A root or primary configuration class pulls in these discrete configuration classes using @Import({ConfigA.class, ConfigB.class}).
Single Entry Point: When booting up AnnotationConfigApplicationContext, developers only need to pass the central class. Spring automatically registers and coordinates all declared beans across the imported classes.
Aggregate with @Import: In your central configuration class (such as AppConfig), annotate the class with @Configuration and @Import({ConfigA.class, ConfigB.class}).
Bootstrap ApplicationContext: Instantiate the Spring container by passing only AppConfig.class into AnnotationConfigApplicationContext.
Verify Bean Availability: Both BeanA and BeanB are instantiated, wired, and accessible from the single application context seamlessly.
Major Architectural Benefits
Enhanced Maintainability: Keeps configuration files concise, domain-driven, and easy to navigate.
Isolated Unit & Integration Testing: Enables test setups to selectively load only relevant configuration modules rather than the full application context.
Explicit Dependencies: Provides clear visibility into configuration dependencies directly through standard Java imports and type references.
Recommended Next Videos
Broaden your Spring JavaConfig and architecture expertise with these related tutorials from our channel:
/**
* Annotate with @Configuration to tell Spring that this is the core
* Spring configuration file, and define bean via @Bean.
*/
@Configuration publicclass EmployeeConfig {
@Bean(name = "employee") public Employee getEmployee() { returnnew Employee(36,"Peter"); }
/**
* Annotate with @Configuration to tell Spring that this is the core
* Spring configuration file, and define bean via @Bean.
*/
@Configuration
@Import({EmployeeConfig.class}) publicclass ApplicationBeans {
Employee employee = (Employee) context.getBean("employee"); System.out.println( "Got employee object from the ApplicationContext(Spring Container)");
employee.displayEmployeeDetails();
}
}
Output
Oct 06, 2018 8:30:01 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f4da5c3: startup date [Sat Oct 06 08:30:01 IST 2018]; root of context hierarchy
Employee(int id, String name) constructor is called by the Spring container
---------------------------------------
Got employee object from the ApplicationContext(Spring Container)
Employee [id=36, name=Peter]
In modern Spring applications, Java-based configuration (JavaConfig) using @Configuration and @Bean has largely replaced traditional XML configurations. A common requirement when defining beans is initializing object properties using setter methods. This approach gives developers complete, type-safe control over object instantiation and property population directly within pure Java code.
Key Annotations Explained
@Configuration: Marks a class as a source of bean definitions for the Spring IoC container, allowing methods to define and manage bean lifecycles.
@Bean: Indicates that a method instantiates, configures, and initializes a new object to be managed by the Spring ApplicationContext.
Setter Injection: After instantiating a class (such as an Employee POJO), its fields are initialized by invoking its setter methods (e.g., setId(), setName()) before returning the bean instance to the container.
Step-by-Step Implementation Flow
Create the POJO: Define the Employee class containing private fields, default constructor, and getter/setter methods.
Create Configuration Class: Annotate your configuration class (e.g., AppConfig) with @Configuration.
Define the @Bean Method: Create a method returning an Employee instance, annotate it with @Bean, create the object with new Employee(), and configure its values via setter calls.
Bootstrap the Container: Load the configuration class into AnnotationConfigApplicationContext and retrieve the configured bean via context.getBean().
Advantages of Java-Based Bean Configuration
Compile-Time Safety: Eliminate runtime typos and syntax issues common in XML bean configurations.
Full Programmatic Control: Seamlessly integrate custom conditional logic, calculations, or external properties when instantiating beans.
Clean IDE Refactoring: Renaming classes, methods, or fields instantly updates across your configuration with full IDE support.
Recommended Next Videos
Continue mastering Spring JavaConfig and bean management with these related tutorials from our channel:
/**
* Annotate with @Configuration to tell Spring that this is the core
* Spring configuration file, and define bean via @Bean.
*/
@Configuration publicclass ApplicationBeans {
@Bean(name = "employee") public Employee getEmployee() {
Employee employee = new Employee();
employee.setId(50);
employee.setName("Peter"); return employee; }
Employee employee = (Employee) context.getBean("employee"); System.out.println( "Got employee object from the ApplicationContext(Spring Container)"); System.out.println(employee);
}
}
Output
Oct 02, 2018 9:13:01 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@5f4da5c3: startup date [Tue Oct 02 09:13:01 IST 2018]; root of context hierarchy
---------------------------------------
Got employee object from the ApplicationContext(Spring Container)
Employee [id=50, name=Peter]