Understanding and Using Spring's @Import Annotation
This article explains the purpose, usage patterns, and internal mechanics of Spring's @Import annotation, including importing regular classes, ImportSelector implementations, and ImportBeanDefinitionRegistrar implementations, with complete code examples and a discussion of how Spring processes these imports at runtime.
The @Import annotation in the Spring framework is a powerful tool that allows ordinary classes, component classes, ImportSelector implementations, and ImportBeanDefinitionRegistrar implementations to be registered in the application context, enabling modular configuration and easier maintenance.
1. How to Use @Import
The annotation has a single value attribute that accepts the class objects to be imported.
1.1 Importing a Regular Class
Even classes that are not annotated with @Component can be added to the Spring container using @Import . For example:
import com.xiakexing.service.OrderService;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(OrderService.class)
public class AppConfig {
} // Ordinary class without @Component
public class OrderService {
public void test() {
System.out.println("Executing OrderService.test");
}
} public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
OrderService orderService = context.getBean("orderService", OrderService.class);
orderService.test();
}
}When this code runs, a No bean named 'orderService' available error occurs because beans imported directly via @Import are registered under their fully‑qualified class name.
1.2 @Import with ImportSelector
The ImportSelector interface lets you dynamically choose which configuration classes to import. It defines two methods: selectImports (returns an array of class names) and getExclusionFilter (returns a Predicate to exclude certain classes).
Example:
public class UserService {
public void test() {
System.out.println("Executing UserService.test");
}
} import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import java.util.function.Predicate;
public class SimpleImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{OrderService.class.getName(), UserService.class.getName()};
}
@Override
public Predicate
getExclusionFilter() {
return name -> name.contains("Order");
}
} @Configuration
@Import(SimpleImportSelector.class)
public class AppConfig {} public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class.getName(), UserService.class);
userService.test();
// OrderService bean is excluded and will cause an error if accessed
}
}1.3 @Import with ImportBeanDefinitionRegistrar
The ImportBeanDefinitionRegistrar interface allows programmatic registration of BeanDefinition objects. Example:
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) { this.name = name; this.age = age; }
// getters, setters, toString omitted for brevity
} import com.xiakexing.entity.User;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class SimpleBeanRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
definition.setBeanClass(User.class);
ConstructorArgumentValues values = new ConstructorArgumentValues();
values.addIndexedArgumentValue(0, "Tom");
values.addIndexedArgumentValue(1, 29);
definition.setConstructorArgumentValues(values);
definition.setScope("singleton");
registry.registerBeanDefinition("user", definition);
}
} @Configuration
@Import(SimpleBeanRegistrar.class)
public class AppConfig {}2. The Internals of @Import
During container startup, ConfigurationClassPostProcessor scans all @Configuration classes and processes their @Import annotations. The processing flow is:
Collect configuration classes and any @Import values.
Invoke processImports which handles three cases: importing regular classes, ImportSelector implementations, and ImportBeanDefinitionRegistrar implementations.
For ImportBeanDefinitionRegistrar , the registrar instances are cached in a map and later each registerBeanDefinitions method is called to register beans.
The ConfigurationClassParser ultimately registers all imported classes as BeanDefinition objects, making them managed by the Spring container.
3. Real‑World Uses in Spring Source Code
Spring uses @Import to provide modular, plug‑in functionality such as AOP and asynchronous execution.
3.1 @EnableAspectJAutoProxy
Adding @EnableAspectJAutoProxy imports AspectJAutoProxyRegistrar (an ImportBeanDefinitionRegistrar ) which registers AnnotationAwareAspectJAutoProxyCreator . This post‑processor creates proxies for beans annotated with @Aspect .
3.2 @EnableAsync
@EnableAsync imports AsyncConfigurationSelector (an ImportSelector ) that selects ProxyAsyncConfiguration . This configuration registers AsyncAnnotationBeanPostProcessor , which creates proxies for methods annotated with @Async .
Overall, @Import is the backbone of Spring’s modular architecture, enabling developers to extend the framework with custom configuration, selectors, and bean registrars.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.