Using @Import for Modular Spring Boot Development and Dynamic Bean Registration
This article explains how to use Spring Boot's @Import annotation to modularize applications, add scanning entry points, and dynamically register beans via ImportSelector and ImportBeanDefinitionRegistrar, including code examples and configuration tips for Maven multi‑module projects.
When developing Spring Boot back‑end applications, a four‑layer architecture can become cumbersome as the project grows, leading to many xxxDAO and xxxService classes.
To keep the codebase manageable, the article suggests splitting a monolithic project into multiple Maven modules and using @Import to bring the beans of each module into the main application context without converting to a distributed micro‑service architecture.
1. Using @ComponentScan
The article reviews how @SpringBootApplication includes @ComponentScan and how specifying scanBasePackages changes the scanning base.
package com.gitee.swsk33.mainmodule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainModuleApplication {
public static void main(String[] args) {
SpringApplication.run(MainModuleApplication.class, args);
}
}2. Basic use of @Import
By annotating a configuration class with @Import(DemoFunction.class) , the specified class is also registered as a bean.
@Configuration
@Import(DemoFunction.class)
public class FunctionImportConfig {}3. Encapsulating @Import in a custom annotation
A custom annotation such as @EnableFunctionOne can be created to import a module’s scanning entry point.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(FunctionOneApplication.class)
public @interface EnableFunctionOne {}4. Dynamic import with ImportSelector
Implementing ImportSelector allows runtime selection of classes to import.
public class DemoImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println("Importing class: " + importingClassMetadata.getClassName());
return new String[]{"com.gitee.swsk33.functionone.FunctionOneApplication",
"com.gitee.swsk33.functiontwo.FunctionTwoApplication"};
}
}5. Dynamic import with ImportBeanDefinitionRegistrar
By implementing ImportBeanDefinitionRegistrar , beans can be registered programmatically.
public class DemoImportRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition bean1 = new GenericBeanDefinition();
bean1.setBeanClass(FunctionOneApplication.class);
registry.registerBeanDefinition("functionOneComponentScan", bean1);
// similarly for FunctionTwoApplication
}
}6. Conditional import
Using @ConditionalOnProperty on the configuration class can enable or disable the import based on application properties.
@Configuration
@Import(FunctionOneApplication.class)
@ConditionalOnProperty(prefix="com.gitee.swsk33.function-one", name="enabled")
public class FunctionImportConfig {}The article concludes that @Import is a powerful tool for Spring Boot modular development, allowing both static and dynamic inclusion of configuration classes and scanning entry points.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
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.