当前位置: 首页 > 知识库问答 >
问题:

具有多个JdbcTemplate和Spring Boot的NoSuchBeanDefinitionException

何兴安
2023-03-14
package my.app;

@SpringBootApplication
@EnableAutoConfiguration
public class Application implements CommandLineRunner {

  @Autowired
  private MyRepository repository;

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    List<Stuff> stuff = repository.getStuff();
  }
}
package my.app;

@Configuration
@ComponentScan
public class AppConfig {
  @Bean(name = "datasource1")
  @ConfigurationProperties(prefix = "db1.datasource")
  public DataSource dataSource1() {
    return DataSourceBuilder.create().build();
  }

  @Bean(name = "db1")
  public DataSource db1(@Qualifier("datasource1" DataSource ds) {
    return new JdbcTemplate(ds);
  }

  @Bean(name = "datasource2")
  @ConfigurationProperties(prefix = "db2.datasource")
  public DataSource dataSource2() {
    return DataSourceBuilder.create().build();
  }

  @Bean(name = "db2")
  public DataSource db1(@Qualifier("datasource1" DataSource ds) {
    return new JdbcTemplate(ds);
  }

}
package my.app;

@Repository
public class MyRepository {
  private JdbcTemplate db1;
  private JdbcTemplate db2;

  @Autowired
  public class MyRepository(@Qualifier("db1") JdbcTemplate db1, @Qualifier("db2") JdbcTemplate db2) {
    this.db1 = db1;
    this.db2 = db2;
  }
}

当我实例化MyRepository时,一切都很好。

我做了一些重构,试图为Db1JdbcTemplate和Db2JdbcTemplate创建新的类,这样我就可以在没有限定符的情况下注入它们。不幸的是,当我这样做时,我会遇到以下异常:

以下是我试图做的:

package my.app;

@Configuration
@ComponentScan
public class AppConfig {
  @Bean(name = "datasource1")
  @ConfigurationProperties(prefix = "db1.datasource")
  public DataSource dataSource1() {
    return DataSourceBuilder.create().build();
  }

  @Bean(name = "datasource2")
  @ConfigurationProperties(prefix = "db2.datasource")
  public DataSource dataSource2() {
    return DataSourceBuilder.create().build();
  }
}
package my.app;

@Component
public class Db1JdbcTemplate extends JdbcTemplate {
  @Autowired
  public Db1JdbcTemplate(@Qualifier("datasource1") DataSource ds1) {
    super(ds1);
  }
} 
package my.app;

@Component
public class Db2JdbcTemplate extends JdbcTemplate {
  @Autowired
  public Db2JdbcTemplate(@Qualifier("datasource2") DataSource ds2) {
    super(ds2);
  }
} 

修改了MyRepository以使用以下内容:

package my.app;

@Repository
public class MyRepository {
  private Db1JdbcTemplate db1;
  private Db2JdbcTemplate db2;

  @Autowired
  public class MyRepository(Db1JdbcTemplate db1, Db2JdbcTemplate db2) {
    this.db1 = db1;
    this.db2 = db2;
  }
}

所以我在这两个上面都有@component注释,所以我希望能够注册和自动连线。然而,当我运行这些东西时,我会得到以下异常:

创建文件[/users/me/spring/target/classes/my/app/myRepository.class]中定义的名为'repository'的bean时出错:通过构造函数参数0表示的依赖项不满足;嵌套异常为org.springframework.beans.factory.noSuchBeanDefinitionException:没有“My.app.db1JDBCTemplate”类型的合格bean可用:至少需要一个合格的自动候选bean。依赖项批注:{}

有什么想法,我需要改变什么,或者如何进一步调试?我总是可以回到工作版本,但我更希望在可能的情况下更加明确,这样编译器就可以帮助我解决问题,而不是由打字的限定符名称引起的运行时错误。

共有1个答案

仲绍晖
2023-03-14

要做到这一点并避免限定符名称中的错别字,一个更标准的方法是避免使用限定符名称,而是使用限定符注释:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface DB1 {
}

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface DB2 {
} 

然后,在定义bean时:

@Configuration
@ComponentScan
public class AppConfig {
  @Bean
  @ConfigurationProperties(prefix = "db1.datasource")
  @DB1
  public DataSource dataSource1() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  @DB1
  public JdbcTemplate db1(@DB1 DataSource ds) {
    return new JdbcTemplate(ds);
  }

  @Bean
  @ConfigurationProperties(prefix = "db2.datasource")
  @DB2
  public DataSource dataSource2() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  @DB2
  public JdbcTemplate db1(@DB2 DataSource ds) {
    return new JdbcTemplate(ds);
  }
}

最后在注入bean时:

public class MyRepository(@DB1 JdbcTemplate db1, @DB2 JdbcTemplate db2) {
    ...
}
 类似资料:
  • 我正在尝试使用springboot访问数据库,但是spring应用程序在下面抛出了一个异常。 创建名为“welcome controller”的bean时出错:注入autowired依赖项失败;嵌套异常为org.springframework.beans.factory.beancreationexception:无法自动连接字段:private org.springframework.jdbc.

  • 问题内容: 我已经在这个论坛上使用了一段时间,以找到一些与SQL有关的问题的答案。现在是时候问一个我已经尝试解决一段时间的问题了。 我有两个表(产品和源)。 我想创建一个SQL SELECT来从源中检索记录列表,并从产品中检索一条附加记录(价格的总和)。我想看到的表应如下所示: source.source_id | source.location | source.source_name | so

  • 这看起来是最简单的事情,但我无法让它工作。 我需要添加文本到多页pdf的第一页(可以是任何页数) 在两页pdf上使用此代码(没有for循环,只使用$pdf- 文档链接 TCPDF类http://www.tcpdf.org/doc/code/classTCPDF.html#a5171e20b366b74523709d84c349c1ced FPDI类http://www.setasign.de/su

  • 问题内容: 我想在Java中实现具有多个值的哈希表,即 并且将返回2倍的值。 我怎样才能做到这一点? 问题答案: 您可以改用Multimap。它在列表中为一个键保留多个值。在commons- collection 和Guava中有实现。 这类似于使用值是列表的Hashmap,但是不必显式创建列表。 自己动手做的同一示例如下所示: 请注意,您可以将Multimap用作构建器,并对其调用asMap以返

  • 问题内容: 我需要一种简单的方法来实现JScrollPane,在其中我可以添加JTextAreas。正如您在youtube和Stackoverflow上看到的那样,这应该像评论系统一样工作。 它应该在Java代码中,如果有的话,我想知道它。 我的评论对象包含: 我将评论保存在数据库中,可以轻松启动它们。问题是显示部分。 谢谢您的帮助 问题答案: 你必须承认,有可能把只有一个JComponent中的