@Conditional注解在实际项目中的使用demo演示
一、demo背景
@Conditional注解一般是和Condition接口配合使用的。
在实际项目中,跨平台适配是常见需求(如文件路径、数据库驱动、消息队列等的差异)。本demo通过@Conditional注解,实现根据操作系统类型动态加载不同文件路径服务的功能:Windows系统加载C:\data\路径,Linux系统加载/var/data/路径,避免硬编码带来的维护成本。
二、demo实现步骤
1. 定义业务接口
首先,定义一个通用的FileService接口,声明获取文件路径的方法:
public interface FileService {
String getFilePath(); // 返回文件存储路径
}
2. 实现不同系统的具体服务
分别实现Windows和Linux系统的文件服务:
// Windows系统实现
public class WindowsFileService implements FileService {
@Override
public String getFilePath() {
return "C:\\data\\"; // Windows路径格式
}
}
// Linux系统实现
public class LinuxFileService implements FileService {
@Override
public String getFilePath() {
return "/var/data/"; // Linux路径格式
}
}
3. 自定义Condition类(核心条件判断)
创建两个Condition实现类,用于判断当前操作系统类型:
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
// Windows系统条件判断
public class WindowsCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 从环境变量中获取操作系统名称(如"Windows 10"、"Linux")
String osName = context.getEnvironment().getProperty("os.name");
boolean flag = osName != null && osName.toLowerCase().contains("windows");
System.out.println("WindowsCondition matches: " + flag);
return flag;
}
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
// Linux系统条件判断
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String osName = context.getEnvironment().getProperty("os.name");
boolean flag = osName != null && osName.toLowerCase().contains("linux");
System.out.println("LinuxCondition matches: " + flag);
return flag;
}
}
4. 配置类:绑定条件与Bean
通过@Conditional注解,将FileService的不同实现与操作系统条件绑定:
@Configuration
public class FileServiceConfig {
// 仅当操作系统为Windows时,加载WindowsFileService
@Bean
@Conditional(WindowsCondition.class)
public FileService windowsFileService() {
return new WindowsFileService();
}
// 仅当操作系统为Linux时,加载LinuxFileService
@Bean
@Conditional(LinuxCondition.class)
public FileService linuxFileService() {
return new LinuxFileService();
}
// 未匹配任何条件时(如macOS),加载默认的MacOSFileService
@Bean
@ConditionalOnMissingBean(FileService.class)
public FileService defaultFileService() {
return new MacOSFileService();
}
}
5. 测试验证
创建一个简单的控制器,验证不同系统下的路径输出:
@RestController
public class FileController {
@Autowired
private FileService fileService; // 自动注入符合条件的Bean
@GetMapping("/file-path")
public String getFilePath() {
return "当前系统文件路径:" + fileService.getFilePath();
}
}
或者使用:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
FileService fileService = (FileService)context.getBean(FileService.class);
System.out.println(fileService.getFilePath());
6. 运行结果
WindowsCondition matches: true
LinuxCondition matches: false
C:\data\
- Windows系统:启动项目后,访问
http://localhost:8080/file-path,返回当前系统文件路径:C:\data; - Linux系统:访问同一接口,返回
当前系统文件路径:/var/data/; - 其他系统(如macOS):若未匹配任何条件,
fileService将为null(可通过@ConditionalOnMissingBean添加默认实现,此处省略)。
三、关键点说明
- 条件判断逻辑:
Condition接口的matches方法通过ConditionContext获取环境变量(os.name),判断操作系统类型; - Bean加载控制:
@Conditional注解将条件与Bean绑定,只有条件满足时,Bean才会被注册到Spring容器; - 单一Bean保证:由于
FileService是接口,且每次只会有一个实现类满足条件,避免了Bean冲突。
四、扩展思考
若需支持更多系统(如macOS),只需新增对应的Condition实现类(如MacCondition)和FileService实现类(如MacFileService),并在配置类中添加对应的@Bean方法即可。这种设计让系统具备良好的扩展性,能适应未来可能的跨平台需求。
浙公网安备 33010602011771号