为什么我不能用 Spring 的 @Value 注释注入我的 PoJo 之一?

Why can't I inject one of my PoJo's with Spring's @Value annotation?

在Spring中,我可以使用@Value 注入配置各种对象,如int、boolean、String 等。 我什至可以通过单个 @Value 注入配置整个映射结构。

假设我们有以下 TCP 服务器规范 class:

public class TcpServerSpec {

    private boolean enabled;
    private String host;
    private int port;

    /* getters & setters */
}

我可以通过名称注入几个服务器规范的映射,做...

@Value("${com.harry.potter.sockets}")
private HashMap<String, TcpServerSpec> sockets;

... 具有以下 YAML 配置(应用程序-test1.yml):

com:
  harry:
    potter:
      sockets:
        server1:
          enabled: true
          host: host1
          port: 1111
        server2:
          enabled: true
          host: host2
          port: 2222

但通常需要介于两者之间:只注入一个 TcpServerSpec:

@Value("${com.harry.potter.sockets.server1}")
private TcpServerSpec server1;

然后我就可以顺利通过以下测试了:

@RunWith(SpringRunner.class)
@SpringBootTest
@ConfigurationProperties("com.harry.potter.sockets")
@TestPropertySource(locations = "classpath:application-test1.yml")
public class MyServerConfiguration1Test {

    @Value("${com.harry.potter.sockets.server1}")
    private TcpServerSpec server1;

    @Value("${com.harry.potter.sockets.server2}")
    private TcpServerSpec server2;

    @Test
    public void testServer1Spec() {
        Assert.assertTrue(server1.isEnabled());
        Assert.assertThat(server1.getHost(), is("host1"));
        Assert.assertThat(server1.getPort(), is(1111));
    }

    @Test
    public void testServer2Spec() {
        Assert.assertTrue(server2.isEnabled());
        Assert.assertThat(server2.getHost(), is("host2"));
        Assert.assertThat(server2.getPort(), is(2222));
    }
}

为什么这不可能? 或者是?

你要的不是@Value而是@ConfigurationProperties.

您可以像这样手动声明您的 bean:

@Configuration
class BeanConfig {
  
  @Bean
  @ConfigurationProperties(prefix = "com.harry.potter.sockets.server1")
  public TcpServerSpec server1() {
    return new TcpServerSpec();
  }

  @Bean
  @ConfigurationProperties(prefix = "com.harry.potter.sockets.server2")
  public TcpServerSpec server2() {
    return new TcpServerSpec();
  }
}

然后用@Qualifier("server1") 和@Qualifier("server2") 注入这些bean。