Spring Boot Annotation配置的时序问题

时间:2015-06-04 19:52:21

标签: java spring-boot spring-annotations

我们在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()方法调用之前被实例化。

我们可以做些什么来解决这个时间问题?我很困惑。

1 个答案:

答案 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)。