我试图理解为什么以下代码会因以下异常而中断:
@Configuration
@EnableMetrics(proxyTargetClass = true)
public class MetricsConfig {
//................
@Bean
@ExportMetricWriter
public MetricWriter statsdMetricWriter() {
return new StatsdMetricWriter("13.127.9.150",8125);
}
}
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'statsdMetricWriter' defined in class path resource [demo/MetricsConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.metrics.writer.MetricWriter]: Factory method 'statsdMetricWriter' threw exception; nested exception is java.lang.NoClassDefFoundError: com/timgroup/statsd/StatsDClientErrorHandler
当我向statsdMetricWriter()添加注释时: @ConditionalOnProperty(prefix =“statsd”,name = {“host”,“port”})
并且提供了@ConfigurationProperties(prefix =“statsd”)公共类StatsdProperties {// ...},上面的Spring配置运行正常。
Spring机器对新的StatsdMetricWriter(String,int)不起作用的要求是什么?
更新以解决@Stéphane的困惑:
是的,这个问题一般也与Spring有关,但我在使用Spring Boot时会遇到它,因此就是那个标签。
我正在尝试将配置类添加到现有应用程序以将其指标导出到statsd服务器,并找到一些相关的示例here和here基于我构建我的拥有Configuration类。当然它并不是空的,为了简洁,我只是简单地复制了相关部分。
我不一定要使用ConditionalOnProperty,但它是上述示例的一部分,如果没有它,它似乎不起作用。
在我这方面的困惑是,即使在像这样的最小配置类中,也不应该说:
@Bean
@ExportMetricWriter
public MetricWriter statsdMetricWriter() {
return new StatsdMetricWriter("10.101.7.130",8125);
}
我想这么想,但上面的例外似乎与我的想法相矛盾。重新访问上述链接并使用 @ConditionalOnProperty(prefix =“statsd”,name = {“host”,“port”})(不包括类路径上的任何其他依赖项)限定工厂方法似乎消除异常。这导致了上述问题。希望能澄清一点。
更新原始问题:
根据下面的评论添加了缺少的依赖项,原始异常消失了,但我想自己澄清@ConditionalOnProperty如何运作。在我目前的设置中有一个配置bean:
@Configuration
@EnableMetrics(proxyTargetClass = true)
@EnableConfigurationProperties(StatsdProperties.class)
public class MetricsConfig {
@Value("${statsd.host:localhost}")
private String host = "localhost";
@Value("${statsd.port:8125}")
private int port;
@Autowired
private StatsdProperties statsdProperties;
//......................
@Bean
@ConditionalOnProperty(prefix = "statsd", name = {"host", "port"})
@ExportMetricWriter
public MetricWriter statsdMetricWriter() {
logger.info("creating statsdMetricWriter....");
return new StatsdMetricWriter(
statsdProperties.getPrefix(),
statsdProperties.getHost(),
statsdProperties.getPort()
);
}
}
和相关的配置属性bean:
@ConfigurationProperties(prefix = "statsd")
public class StatsdProperties {
@Value("${statsd.host:13.127.9.150}")
private String host;
@Value("${statsd.port:8125}")
private int port;
private String prefix;
//getters & setters
在执行@ConditionalOnProperty注释时不清楚:
它如何解释属性的存在 - 它是applicationaiton.properties文件中的值存在(似乎有效),还是作为@Value注释的默认值存在的值(它不存在)在我的测试中似乎考虑到了考虑因素)?或者别的什么呢?
什么是更好的做法 - 在@Configuration类中或在@ConfigurationProperties类或其他地方使用@Value?
另外,在语义上,@ ConditionalOnProperty似乎有点误导,对我来说它暗示了类中特定属性的存在。听起来真正试图断言的是@ConditionalOnPropertyValue,还是我不明白?
提前谢谢。