如何调试 Spring Boot 自动配置

Jen*_*der 3 java spring spring-boot spring-autoconfiguration

使用 Spring Boot 时的一个常见问题模式是缺少一个 bean,尽管该 bean 期望它由 Spring Boot 创建。

如何调试这样的场景?如何找出该 Bean 没有按预期创建的原因!

注意:我创建了这个问题,它是针对特殊情况提出的问题的答案。我希望这对各种场景都有帮助。

Jen*_*der 6

  1. debug=true通过添加到您的文件来启用 Spring Boot 的调试application.properties

    这会在启动期间创建日志输出。对于每个可用的自动配置,它包含是否“匹配”的信息,即是否满足其先决条件,以及这些条件是什么。

  2. 特别是在Negative matches输出部分中查看应该发生但没有发生的自动配置。在日志中搜索相关技术是个好主意。

  3. 您在上一步中找到的自动配置可能暗示其他未激活的自动配置。对于这些重复步骤 2。

以下是搜索https://github.com/iosenberg/todo/commit/c4cfbf63132e251ce98cfe02178bd48cc447aac7的示例 Spring boot 中引用了找不到存储库 bean

缺少的 bean 是 Spring Data JDBC 存储库。因此datasourcejdbc作为第一个搜索词出现在我的脑海中。搜索JDBC会产生以下似乎相关的结果:

   DataSourceAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition)
      - @ConditionalOnMissingBean (types: io.r2dbc.spi.ConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition)

   DataSourceTransactionManagerAutoConfiguration matched:
      - @ConditionalOnClass found required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.transaction.TransactionManager' (OnClassCondition)
Run Code Online (Sandbox Code Playgroud)

这看起来像有一个DataSource,它只是表明你不应该在第一场比赛时停止。

下一场比赛是:

   DataSourceInitializationConfiguration:
      Did not match:
         - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) did not find any beans (OnBeanCondition)
      Matched:
         - @ConditionalOnClass found required class 'org.springframework.jdbc.datasource.init.DatabasePopulator' (OnClassCondition)
Run Code Online (Sandbox Code Playgroud)

所以,DataSourceAutoConfiguration确实跑了,但我们似乎仍然没有豆子DataSource。由此我们了解到,可用的类和可用的该类型的 Bean 之间存在重要区别。当你大声说出来时,这一点很明显,但当你查看某些日志文件时,很容易错过。

搜索的其余部分会发现更多不起作用的东西,这要么是不相关的,要么如果没有DataSourcebean 就不足为奇了。因此我转而在日志中搜索数据源。

这会带来大量点击。但第一个Negative matches确实很有帮助。

   DataSourceAutoConfiguration.EmbeddedDatabaseConfiguration:
      Did not match:
         - EmbeddedDataSource did not find embedded database (DataSourceAutoConfiguration.EmbeddedDatabaseCondition)
Run Code Online (Sandbox Code Playgroud)

所以没有找到嵌入式数据库!它试图使用什么数据库?检查application.propertiesJDBC url 显示没有。检查依赖关系显示有一个嵌入式数据库,但仅限范围test,因此对于主程序来说没有可用的 JDBC 驱动程序。通过使内存数据库依赖项可用于主应用程序解决了这个问题。