好的!我用两个实际的代码例子来演示 @Import
的第二种(动态选择)和第三种(高级自定义)用法,保证你一看就懂!
示例1:动态选择配置(ImportSelector
)
场景:根据当前操作系统(Windows/Linux)自动加载不同的配置
java
// 1. 定义两个不同的配置类
@Configuration
public class WindowsConfig {
@Bean
public CommandRunner windowsRunner() {
return () -> System.out.println("Running dir command (Windows)");
}
}
@Configuration
public class LinuxConfig {
@Bean
public CommandRunner linuxRunner() {
return () -> System.out.println("Running ls command (Linux)");
}
}
// 2. 实现智能选择器
public class OsImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return new String[]{WindowsConfig.class.getName()}; // 返回Windows配置类全限定名
} else {
return new String[]{LinuxConfig.class.getName()}; // 返回Linux配置类全限定名
}
}
}
// 3. 使用动态导入
@Configuration
@Import(OsImportSelector.class) // 关键!动态选择配置
public class AppConfig {
}
// 4. 测试
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CommandRunner runner = context.getBean(CommandRunner.class);
runner.run(); // 输出取决于操作系统!
}
效果:
- 在 Windows 下运行 → 执行
dir
命令逻辑 - 在 Linux 下运行 → 执行
ls
命令逻辑
示例2:高级自定义注册(ImportBeanDefinitionRegistrar
)
场景 :动态注册所有实现了 MyPlugin
接口的类(模拟插件系统)
java
// 1. 定义插件接口
public interface MyPlugin {
void execute();
}
// 2. 实现两个插件
public class LogPlugin implements MyPlugin {
@Override
public void execute() {
System.out.println("记录日志...");
}
}
public class EmailPlugin implements MyPlugin {
@Override
public void execute() {
System.out.println("发送邮件...");
}
}
// 3. 实现动态注册器
public class PluginRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 扫描包路径下所有实现MyPlugin的类
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AssignableTypeFilter(MyPlugin.class));
for (BeanDefinition bd : scanner.findCandidateComponents("com.example")) {
// 将每个插件类注册为Bean
String beanName = StringUtils.uncapitalize(bd.getBeanClassName().substring(
bd.getBeanClassName().lastIndexOf(".") + 1));
registry.registerBeanDefinition(beanName, bd);
}
}
}
// 4. 启用插件系统
@Configuration
@Import(PluginRegistrar.class) // 关键!动态注册插件
public class PluginConfig {
}
// 5. 测试
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(PluginConfig.class);
Map<String, MyPlugin> plugins = context.getBeansOfType(MyPlugin.class);
plugins.values().forEach(MyPlugin::execute); // 执行所有插件
}
效果 :
输出:
erlang
记录日志...
发送邮件...
关键点总结
方式 | 实际应用场景 | 代码特征 |
---|---|---|
ImportSelector | 根据条件(环境、配置等)动态加载配置 | 实现 selectImports() 返回类全名 |
ImportBeanDefinitionRegistrar | 需要完全控制Bean的注册过程 | 实现 registerBeanDefinitions() 手动注册 |
这两个例子展示了如何灵活使用 @Import
实现:
- 智能装配(自动适应不同环境)
- 插件化架构(动态发现和注册组件)