为何无法使用Spring的@Value注解注入自定义POJO实例?
问题原因
@Value 注解原生仅支持基础类型、包装类型、字符串、数组、基础集合类型的注入,本身不具备将结构化配置自动绑定到自定义POJO的能力。你之前可以成功注入HashMap<String, TcpServerSpec>是Spring Boot @ConfigurationProperties的绑定能力提供的支持,并非@Value原生功能。
另外你的测试代码存在两处错误:
@ConfigurationProperties注解加在测试类上不会生效,该注解需要标注在配置类或待绑定的POJO类上才会触发配置绑定逻辑@TestPropertySource默认不支持YAML格式配置文件的加载,需要额外指定YAML解析工厂才能正常读取yml内容
可行解决方案
方案1:统一配置绑定类(最推荐)
定义专门的配置绑定类,统一管理所有TCP服务规格实例:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import java.util.Map; @Configuration @ConfigurationProperties(prefix = "com.harry.potter") public class TcpServerConfig { private Map<String, TcpServerSpec> sockets; // getters and setters public Map<String, TcpServerSpec> getSockets() { return sockets; } public void setSockets(Map<String, TcpServerSpec> sockets) { this.sockets = sockets; } }
需要使用时直接注入配置类,按需获取对应实例即可:
@Autowired private TcpServerConfig tcpServerConfig; // 取单个实例 TcpServerSpec server1 = tcpServerConfig.getSockets().get("server1");
方案2:单独绑定单个POJO
如果仅需要使用单个服务规格实例,可以直接给对应POJO加绑定注解:
@Configuration @ConfigurationProperties(prefix = "com.harry.potter.sockets.server1") public class Server1Spec extends TcpServerSpec{ }
注入时直接注入这个类的实例即可:
@Autowired private Server1Spec server1;
测试代码修正
如果要在测试类中加载YAML配置,需要自定义YAML属性源工厂:
import org.springframework.boot.env.YamlPropertySourceLoader; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.DefaultPropertySourceFactory; import org.springframework.core.io.support.EncodedResource; import java.io.IOException; import java.util.List; public class YamlPropertySourceFactory extends DefaultPropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()); return sources.get(0); } }
测试类上的@TestPropertySource指定工厂即可:
@TestPropertySource(locations = "classpath:application-test1.yml", factory = YamlPropertySourceFactory.class)
内容的提问来源于stack exchange,提问作者JBStonehenge
相关产品推荐
相关产品推荐

