我们在Spring启动应用程序中对bean,存储库和控制器的计时有一个奇怪的问题。
我们有一个由Map支持的NodeRepository。这个Map对象应该是我们使用@Bean注释创建的Map,但似乎Spring正在创建自己的Map并将其注入我们的NodeRepository。这是一个问题,因为Map中的键是错误的,因为Spring假设我们的键值。
以下是所有需要的代码:
org.xxx.Application
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Bean
public Map<String, RemoteNode> getRemoteNodeMap() {
HashMap<String, RemoteNode> remoteNodeMap = new HashMap<>();
remoteNodeMap.put("NODE1", this.getRemoteNode1());
remoteNodeMap.put("NODE2", this.getRemoteNode2());
return remoteNodeMap;
}
@Bean(name = "remoteNode1")
public RemoteNode getRemoteNode1() {
return new DefaultRemoteNode("NODE1");
}
@Bean(name = "remoteNode2")
public RemoteNode getRemoteNode2() {
return new DefaultRemoteNode("NODE2");
}
}
org.xxx.repository.RemoteNodeRepository
@Repository
public class RemoteNodeRepositoryImpl implements RemoteNodeRepository {
private Map<String, RemoteNode> remoteNodeMap;
@Autowired
public RemoteNodeRepository(Map<String, RemoteNode> remoteNodeMap) {
this.remoteNodeMap = remoteNodeMap;
}
}
我希望注入RemoteNodeRepsoitory的是一张如下所示的地图:
“NODE1”,REMOTENODE( “NODE1”)
“NODE2”,REMOTENODE( “NODE2”)
但是,这是注入RemoteNodeRepository的Map:
“remoteNode1”,REMOTENODE( “NODE1”)
“remoteNode2”,REMOTENODE( “NODE2”)
注意,键的名称基于Application类中@Bean注释的名称。如果我们删除@Bean的'name'限定符,则按照方法命名。
如果我们将@Qualifier注释添加到RemoteNodeRepsoitory的Map属性中,我们会得到以下异常:
引起: org.springframework.beans.factory.NoSuchBeanDefinitionException:没有 找到类型为[org.chronopolis.remote.node.RemoteNode]的限定bean for dependency [map with value type org.chronopolis.remote.node.RemoteNode]:预计至少有1个bean 它有资格作为此依赖关系的autowire候选者。依赖 注释: {@ org.springframework.beans.factory.annotation.Qualifier(值= remoteNodeMap)}
最后,在调试器中设置断点时,我们可以清楚地看到RemoteNodeRepository在Application类中的getRemoteNodeMap()方法调用之前被实例化。
我们可以做些什么来解决这个时间问题?我很困惑。
答案 0 :(得分:1)
我不认为这是时间问题。您与此弹簧功能(来自http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/)
“存在冲突”只要预期的密钥类型是,即使是类型化的地图也可以自动装配 串。 Map值将包含预期类型的所有bean, 并且键将包含相应的bean名称:
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
说实话,我不确定你是否可以轻易“覆盖”这个,但是简单的解决方法应该可行 - 只需使用一些包装类使你的类型特别 - 类似于(伪代码):
class NodeMap {
Map<String, RemoteNode> map;
}
然后在@Bean
定义和自动装配时使用它。或者只是不创建地图并使用弹簧功能(也可以重命名节点bean)。