13

要使用@ConfigurationProperties注释,必须创建一个带有 getter 和 setter 的类,如下所示:

@ConfigurationProperties(prefix = "some")
public class PropertiesConfig {
    private boolean debug;

    public boolean isDebug() {
        return debug;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }
}

但这会导致有人试图通过调用来修改此值:

@Autowire
private PropertiesConfig config;        
//....

config.setDebug(true);

有没有办法在@ConfigurationProperties没有设置器和外部解析器/读取器类的情况下创建带注释的类?

4

4 回答 4

5

使用尽可能少的样板代码的一种方法是仅使用带有 getter 的接口

public interface AppProps {
    String getNeededProperty();
}

@Getter并在 Lombok和@Setter注释的帮助下摆脱了实现中的样板 getter 和 setter :

@ConfigurationProperties(prefix = "props")
@Getter
@Setter
public class AppPropsImpl implements AppProps {
    private String neededProperty;
}

然后,对于只能通过接口访问其他 bean 的 bean bo,可以考虑将其放入将通过接口公开它的配置中,而不是将其标记为@Component或在主应用程序类上使用:@EnableConfigurationProperties(AppPropsImpl.class)

@Configuration
@EnableConfigurationProperties
public class PropsConfiguration  {
    @Bean
    public AppProps appProps(){
        return new AppPropsImpl();
    }
}

现在这个 bean 只能通过使用接口来注入,这使得 setter 不能用于其他 bean:

public class ApplicationLogicBean {
    @Autowired
    AppProps props;

    public void method(){
        log.info("Got " + props.getNeededProperty());
    }
}

使用 Spring Boot 1.5.3 和 Lombok 1.16.16 进行测试。

于 2017-06-25T21:44:32.883 回答
3

像这样的东西很好用

@Configuration
class MyAppPropertiesConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "some")
    public PropertiesConfig propertiesConfig () {
        return new PropertiesConfigImpl();
    }

    public interface PropertiesConfig {
            public boolean isDebug();
    }

    private static class PropertiesConfigImpl implements PropertiesConfig {
        private boolean debug;

        @Override
        public boolean isDebug() {
            return debug;
        }

        public void setDebug(boolean debug) {
            this.debug = debug;
        }
    }
}

接着

@Autowired PropertiesConfig properties;
于 2018-04-04T13:29:19.537 回答
3

从 Spring Boot 2.2 开始,终于可以定义用@ConfigurationProperties. 非常感谢 Spring 开发人员不断改进他们的框架。
该文档显示了一个示例。
您只需要声明一个带有要绑定的字段的构造函数(而不是 setter 方式):

@ConstructorBinding
@ConfigurationProperties(prefix = "some")
public class PropertiesConfig {
    private boolean debug;

    public AcmeProperties(boolean enabled) {
        this.enabled = enabled;   
    }

    public boolean isDebug() {
        return debug;
    }

}

注意 1:您必须定义一个且只有一个带有参数的构造函数来绑定:

在此设置中,只有一个构造函数必须使用您希望绑定的属性列表定义,并且除了构造函数中的属性之外,不得绑定其他属性。

注 2:@DefaultValue引入 a 是为了定义不可变属性绑定的默认值。

可以使用@DefaultValue 指定默认值,并且将应用相同的转换服务将字符串值强制为缺失属性的目标类型。

这是从官方文档中获取的更详细的示例:

import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DefaultValue;
import org.springframework.boot.context.properties.ConstructorBinding;

@ConstructorBinding
@ConfigurationProperties("acme")
public class AcmeProperties {

    private final boolean enabled;

    private final InetAddress remoteAddress;

    private final Security security;

    public AcmeProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    public boolean isEnabled() { ... }

    public InetAddress getRemoteAddress() { ... }

    public Security getSecurity() { ... }

    public static class Security {

        private final String username;

        private final String password;

        private final List<String> roles;

        public Security(String username, String password,
                @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        public String getUsername() { ... }

        public String getPassword() { ... }

        public List<String> getRoles() { ... }

    }

}
于 2019-07-18T20:23:19.760 回答
1

不可能开箱即用。@ConfigurationPropertiesbean 必须有标准的 getter 和 setter。您可能需要考虑此答案中描述的方法:Immutable @ConfigurationProperties

或者是这样的:

@Component
public class ApplicationProperties {

  private final String property1;
  private final String property2;

  public ApplicationProperties(
    @Value("${some.property1"}) String property1,
    @Value("${some.other.property2}) String property2) {
    this.property1 = property1;
    this.property2 = property1;
  }

  //
  // ... getters only ...
  //

}
于 2017-06-24T04:39:01.557 回答