【问题标题】:Spring can't autowire classSpring不能自动装配类
【发布时间】:2015-09-17 02:54:17
【问题描述】:

我有以下 Spring @Configuration:

@Bean
@Qualifier("mongo")
public MongoFacade mongo(Environment env){
    final String host = env.getProperty("database.host");
    final MongoClient mongoClient = new MongoClient(host);
    return new MongoFacade(mongoClient, "test-db");
}

@Bean
public MessageStore<Event> eventStore(@Qualifier("mongo") MongoFacade mongo, ObjectMapper mapper) {
    return new MongoMessageStore<>(mongo, mapper);
}

当我启动我的应用程序时,会引发异常,原因是:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'eventStore' defined in it.m.MyConfiguration: Unsatisfied dependency expressed through constructor argument with index 0 of type [base.backend.persistence.impl.mongo.MongoFacade]: : No qualifying bean of type [base.backend.persistence.impl.mongo.MongoFacade] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=mongo)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [base.backend.persistence.impl.mongo.MongoFacade] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Qualifier(value=mongo)}

MongoFacade 类是一个真正的类,并且不实现接口,我也尝试从方法中删除Environment 依赖,但仍然不起作用。

删除@Qualifier 注释错误是:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [base.backend.persistence.impl.mongo.MongoFacade] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

MongoFacade 是 MongoClient 类的一个简单外观,可与我的 PersistenceId 类一起使用:

public class MongoFacade {

public static final String DEFAULT_NAME = "default";

private final MongoClient mongo;
private final String defaultName;

public MongoFacade(MongoClient mongoClient) {
    this(mongoClient, DEFAULT_NAME);
}
public MongoFacade(MongoClient mongoClient, String defaultName) {
    this.mongo = mongoClient;
    this.defaultName = defaultName;
}

public Document findOne(PersistenceId id){
    final MongoCollection<Document> collection = collection(id);
    final String documentId = documentId(id);

    return collection.find(eq("_id", documentId)).first();
}

public UpdateResult updateOne(PersistenceId id, Document update) {
    final MongoCollection<Document> collection = collection(id);
    final String documentId = documentId(id);

    return collection.updateOne(eq("_id", documentId), update);
}

【问题讨论】:

  • 你能粘贴一下 MongoFacade 的样子吗?
  • ok 已将课程添加到问题中
  • 你不是在这里缺少@Autowired 吗?@Bean public MessageStore eventStore( HERE@Autowired @Qualifier("mongo") MongoFacade mongo, ObjectMapper mapper) { return new MongoMessageStore(mongo , 映射器); }
  • 不,不需要,问题是方法名...

标签: java spring spring-boot inversion-of-control


【解决方案1】:

环境可以作为字段而不是构造函数注入,我建议使用方法调用而不是依赖项的自动连接。

类似下面的内容

@Autowired
private Environment env;

@Bean
public MongoFacade mongoFacade(){
    final String host = env.getProperty("database.host");
    final MongoClient mongoClient = new MongoClient(host);
    return new MongoFacade(mongoClient, "test-db");
}

@Bean
public MessageStore<Event> eventStore(ObjectMapper mapper) {
    return new MongoMessageStore<>(mongoFacade(), mapper);
}

编辑:添加了 Spring Boot MongoDB 配置

从 cmets 很明显您正在使用 Spring Boot,这已经为您提供了 auto configuresMongoClient。您可以进一步减少配置,而不是自己做。 (另见MongoAutoConfiguration)。

在你的application.properties 添加

spring.data.mongodb.host=<value of current database.host>

或者如果它是一个完整的 URI

spring.data.mongodb.uri=<value of current database.host>

然后更改您的配置类。

@Bean
public MongoFacade mongoFacade(MongoClient mongoClient){
    return new MongoFacade(mongoClient, "test-db");
}

@Bean
public MessageStore<Event> eventStore(ObjectMapper mapper) {
    return new MongoMessageStore<>(mongoFacade(null), mapper);
}

Spring Boot 现在将构造一个MongoClient

【讨论】:

  • 用方法调用不是创建了两次对象吗?
  • 没有。该类以特殊方式处理,并创建一个代理来拦截方法调用。
  • arg...spring 有太多的魔力...我已经更改了我的代码,现在我遇到了这个异常:Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [base.backend.persistence.contract.MessageStore]: Factory method 'eventStore' threw exception; nested exception is java.lang.ClassCastException: com.mongodb.MongoClient cannot be cast to base.backend.persistence.impl.mongo.MongoFacade 这个 ClassCastException 让我心烦...
  • Ehrm 我简直不敢相信它会起作用,将方法的名称从 mongo 更改为 mongoFacade 并请重新添加 @Bean 方法,否则它不会是一个弹簧托管 bean(例如,如果它包含回调,则可能需要它)。
  • 让我猜猜MessageStore 有一个名为MongoClient 的字段mongo
【解决方案2】:

你能不能在声明 bean 定义时使用 @Service 而不是 @qualifier

@Service("mongo")
public MongoFacade mongoFacade()

让我知道它是否适合你。

【讨论】:

    猜你喜欢
    • 2012-03-14
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 2011-12-31
    • 2012-02-24
    • 2018-12-02
    • 1970-01-01
    相关资源
    最近更新 更多