根据一些任意的系统状态,有条件地启用或禁用一个完整的 @Configuration 类,甚至是个别的 @Bean 方法,往往是很有用的。一个常见的例子是使用 @Profile 注解来激活 Bean,只有在 Spring 环境中启用了特定的配置文件时(详见 Bean 定义配置文件)。

    @Profile 注解实际上是通过使用一个更灵活的注解 @Conditional 来实现的。@Conditional 注解指出了特定的 org.springframework.context.annotation.Condition实现,在注册一个 @Bean 之前应该参考这些实现。

    Condition 接口的实现提供了一个 matches(...) 方法,它返回 true 或 false。例如,下面的列表显示了用于 @Profile 的实际 Condition 实现。

    1. @Override
    2. public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    3. // 读取 @Profile 注解属性
    4. MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
    5. if (attrs != null) {
    6. for (Object value : attrs.get("value")) {
    7. if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
    8. return true;
    9. }
    10. }
    11. return false;
    12. }
    13. return true;
    14. }

    简单说:你的开发环境是 dev, 在配置文件中 application.properties 标识如下

    1. spring.profiles.active=dev

    但是你想要一个配置类只能在 prod 中才能生效,只需要这样做

    1. package cn.mrcode.study.springdocsread.web;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.context.annotation.Profile;
    5. import org.springframework.context.annotation.Scope;
    6. /**
    7. * @author mrcode
    8. */
    9. @Configuration
    10. @Profile("prod") // 这里指定生效的环境
    11. public class AppConfig {
    12. @Bean
    13. @Scope("prototype")
    14. public Command asyncCommand() {
    15. Command command = new Command();
    16. // 根据需要在这里注入依赖性
    17. return command;
    18. }
    19. @Bean
    20. public CommandManager commandManager() {
    21. System.out.println("xcc");
    22. // 用 createCommand() 返回 CommandManager 的新匿名实现。
    23. // 重载以返回一个新的 多例的 Command 对象
    24. return new CommandManager() {
    25. protected Command createCommand() {
    26. return asyncCommand();
    27. }
    28. };
    29. }
    30. }

    有关更多细节,请参见 @Conditional javadoc