记一次spring注解@Value不生效的深度排查
上周遇到一个有意思的问题,拿出来分享一下。
问题可以简单地描述如下:在
@Configuration
public class DubboRegistryConfig {
@Value("${dynamic.dubbo.registries.nacos.address:#{null}}")
private String nacosAddress;
@Value("${dynamic.dubbo.registries.zk.address:#{null}}")
private String zkAddress;
@Bean
public RegistryConfig nacosRegistry() {
RegistryConfig nacosConfig = new RegistryConfig();
nacosConfig.setAddress(nacosAddress);
nacosConfig.setProtocol("nacos");
return nacosConfig;
}
@Bean
public RegistryConfig zkRegistry() {
RegistryConfig zkConfig = new RegistryConfig();
zkConfig.setAddress(zkAddress);
zkConfig.setProtocol("zookeeper");
return zkConfig;
}
@Bean
public ConsumerConfig consumerConfig() {
ConsumerConfig consumerConfig = new ConsumerConfig();
List registryConfigs = new ArrayList<>(2);
registryConfigs.add(nacosRegistry());
registryConfigs.add(zkRegistry());
consumerConfig.setRegistries(registryConfigs);
return consumerConfig;
}
@Bean
public ProviderConfig providerConfig() {
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setRegistry(zkRegistry());
return providerConfig;
}
}
将这段代码打成jar包,在主工程中引入,启动类上使用
@SpringBootApplication
@Import(DubboRegistryConfig.class)
public class Application {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(Application.class);
application.run(args);
}
}
当然,注册中心地址写在
运行一下,奇怪的事情发生了,方便起见,我把调试截图贴出来

当运行到
ConfigurationClassPostProcessor.enhanceConfigurationClasses()|Cannot enhance @Configuration bean definition 'com.lkxiaolou.registry.dynamic.config.DubboRegistryConfig' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
大概意思是,由于
@Configuration
public class DubboRegistryConfig {
@Value("${dynamic.dubbo.registries.nacos.address:#{null}}")
private String nacosAddress;
@Value("${dynamic.dubbo.registries.zk.address:#{null}}")
private String zkAddress;
@PostConstruct
public void init() {
System.out.println("=== DubboRegistryConfig inited");
}
@Bean
@DependsOn("dubboRegistryConfig")
public RegistryConfig nacosRegistry() {
System.out.println("=== nacosRegistry create");
RegistryConfig nacosConfig = new RegistryConfig();
nacosConfig.setAddress(nacosAddress);
nacosConfig.setProtocol("nacos");
return nacosConfig;
}
@Bean
public RegistryConfig zkRegistry() {
System.out.println("=== zkRegistry create");
RegistryConfig zkConfig = new RegistryConfig();
zkConfig.setAddress(zkAddress);
zkConfig.setProtocol("zookeeper");
return zkConfig;
}
@Bean
public ConsumerConfig consumerConfig() {
System.out.println("=== consumerConfig create");
ConsumerConfig consumerConfig = new ConsumerConfig();
List registryConfigs = new ArrayList<>(2);
registryConfigs.add(nacosRegistry());
registryConfigs.add(zkRegistry());
consumerConfig.setRegistries(registryConfigs);
return consumerConfig;
}
@Bean
public ProviderConfig providerConfig() {
System.out.println("=== providerConfig create");
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setRegistry(zkRegistry());
return providerConfig;
}
}
最后只有三个bean正常输出了调试信息
=== consumerConfig create
=== nacosRegistry create
=== zkRegistry create

发现在
于是把

先捋一捋,我们最初的问题是
bean生成了,但

从堆栈中发现了是dubbo的

那么为什么
接着调试,发现Spring容器初始化的时候初始化了

那么问题归结于,为什么在
接着调试,

通过调试发现问题就出在注入
注入


这个方法就会初始化bean了,这是为什么?
原来
那为什么判断类型时
差不多到这里已经水落石出了,我们简单总结一下:
问题找到了,解决就很简单,这种情况下不要使用这两种注解,可以实现
最后,文章中还有几处没有详细写出来,大家伙可以试着分析分析,一是为什么@Import导入的jar包中的@Configuration不是一个bean?另一个是文章中第一次执行程序输出日志有什么意义?
