在Spring Boot中根据环境控制CommandLineRunner执行
CommandLineRunner及任何spring的bean都可以根据不同的Spring环境(profile)决定是否执行业务逻辑。以下是CommandLineRunner场景下的几种实现方式:
1. 使用@Profile注解控制整个Runner
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile("dev") // 只在dev环境执行
public class DevCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("Dev环境初始化逻辑执行");
}
}
@Component
@Profile("prod") // 只在prod环境执行
public class ProdCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("生产环境初始化逻辑执行");
}
}2. 在run方法内判断环境
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class EnvironmentAwareRunner implements CommandLineRunner {
private final Environment env;
public EnvironmentAwareRunner(Environment env) {
this.env = env;
}
@Override
public void run(String... args) throws Exception {
if (env.acceptsProfiles("dev")) {
System.out.println("执行开发环境特定逻辑");
} else if (env.acceptsProfiles("prod")) {
System.out.println("执行生产环境特定逻辑");
}
// 所有环境都执行的公共逻辑
System.out.println("公共初始化逻辑");
}
}3. 使用条件注解组合
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Component
@ConditionalOnProperty(
value = "app.feature.enabled",
havingValue = "true",
matchIfMissing = false
)
public class ConditionalRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("仅在app.feature.enabled=true时执行");
}
}4. 针对RocketMQ消费者的环境控制实现
import org.apache.rocketmq.client.apis.consumer.PushConsumer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile("!test") // 在非test环境执行
public class RocketMQConsumerRunner implements CommandLineRunner {
private final PushConsumer pushConsumer;
public RocketMQConsumerRunner(PushConsumer pushConsumer) {
this.pushConsumer = pushConsumer;
}
@Override
public void run(String... args) throws Exception {
// 只有非测试环境才启动消费者
System.out.println("RocketMQ消费者在非测试环境下启动");
}
}5. 动态决定是否执行的更复杂逻辑
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class SmartRunner implements CommandLineRunner {
private final Environment env;
public SmartRunner(Environment env) {
this.env = env;
}
@Override
public void run(String... args) throws Exception {
boolean shouldRun = shouldExecuteBusinessLogic();
if (shouldRun) {
System.out.println("执行业务逻辑");
// 实际业务代码...
} else {
System.out.println("跳过业务逻辑执行");
}
}
private boolean shouldExecuteBusinessLogic() {
// 复杂的环境判断逻辑
return env.acceptsProfiles("dev", "staging") ||
!env.containsProperty("disable.runner");
}
}配置示例
在application-dev.yml中:
spring:
profiles:
active: dev
app:
feature:
enabled: true在application-prod.yml中:
spring:
profiles:
active: prod
app:
feature:
enabled: false最佳实践建议
- 简单场景使用
@Profile注解 - 复杂条件使用
Environment判断或@Conditional系列注解 - 避免在Runner中做耗时操作,特别是生产环境
- 考虑使用
ApplicationRunner替代CommandLineRunner,它提供了更丰富的ApplicationArguments参数处理 - 测试时可以使用
@MockBean替换真实的Runner实现
通过以上方式,你可以灵活控制不同环境下CommandLineRunner的执行行为,满足各种初始化需求。
















