写在前面

这个demo来说明怎么一步步排查一个常见的spring boot AutoConfiguration的错误。

https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-database-type-NONE

调试排查 Cannot determine embedded database driver class for database type NONE 的错误

把工程导入IDE里,直接启动应用,抛出来的异常信息是:


Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-11-29 14:26:34.478 ERROR 29736 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : ***************************
APPLICATION FAILED TO START
*************************** Description: Cannot determine embedded database driver class for database type NONE Action: If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).

其实这时有两个思路,直接google搜索Cannot determine embedded database driver class for database type NONE,就可以找到解决办法。

第二种方式,仔细查看日志内容,可以发现有To display the auto-configuration report re-run your application with 'debug' enabled.

搜索下这个,就可以在spring的官方网站上找到相关的信息:https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html

就是用户只要配置了debug这个开关,就会把auto-configuration 相关的信息打印出来。

熟悉spring的环境变量注入的话,就可以知道有几种打开这个的方式:

  • args里增加--debug
  • 在application.properties里增加debug=true
  • 通过-Ddebug=true

增加debug开关之后的信息

增加debug开关之后,可以看到打印出了错误堆栈:

2017-11-29 14:33:08.776 DEBUG 29907 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : Application failed to start due to an exception

org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:245) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:182) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:42) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat.dataSource(DataSourceConfiguration.java:53) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]

抛出异常的代码是:

    /**
* Determine the driver to use based on this configuration and the environment.
* @return the driver to use
* @since 1.4.0
*/
public String determineDriverClassName() {
if (StringUtils.hasText(this.driverClassName)) {
Assert.state(driverClassIsLoadable(),
"Cannot load driver class: " + this.driverClassName);
return this.driverClassName;
}
String driverClassName = null; if (StringUtils.hasText(this.url)) {
driverClassName = DatabaseDriver.fromJdbcUrl(this.url).getDriverClassName();
} if (!StringUtils.hasText(driverClassName)) {
driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
} if (!StringUtils.hasText(driverClassName)) {
throw new DataSourceBeanCreationException(this.embeddedDatabaseConnection,
this.environment, "driver class");
}
return driverClassName;
}

可以看出来是没有找到 DataSource 的driver class,然后抛出了 DataSourceBeanCreationException

那么一种解决办法是,在maven依赖里加入一些 DataSource driver class。

但是应用自己的代码里并没有使用DataSource,哪里导致spring boot要创建一个DataSource对象?

哪里导致spring boot要创建DataSource

从异常栈上,可以找到DataSourceConfiguration$Tomcat 这个类,那么查找下它的引用,可以发现它是被org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.PooledDataSourceConfiguration import引入的。

    @Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration { }

那么 PooledDataSourceConfiguration 是怎么生效的呢?从代码上可以看到@Conditional(PooledDataSourceCondition.class)

那么再看PooledDataSourceCondition的具体实现:

    /**
* {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
* is set or {@link PooledDataSourceAvailableCondition} applies.
*/
static class PooledDataSourceCondition extends AnyNestedCondition { PooledDataSourceCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
} @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
static class ExplicitType { } @Conditional(PooledDataSourceAvailableCondition.class)
static class PooledDataSourceAvailable { } }

PooledDataSourceCondition引入了@Conditional(PooledDataSourceAvailableCondition.class) :

    /**
* {@link Condition} to test if a supported connection pool is available.
*/
static class PooledDataSourceAvailableCondition extends SpringBootCondition { @Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("PooledDataSource");
if (getDataSourceClassLoader(context) != null) {
return ConditionOutcome
.match(message.foundExactly("supported DataSource"));
}
return ConditionOutcome
.noMatch(message.didNotFind("supported DataSource").atAll());
} /**
* Returns the class loader for the {@link DataSource} class. Used to ensure that
* the driver class can actually be loaded by the data source.
* @param context the condition context
* @return the class loader
*/
private ClassLoader getDataSourceClassLoader(ConditionContext context) {
Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
.findType();
return (dataSourceClass == null ? null : dataSourceClass.getClassLoader());
} }

从代码里,可以看到是尝试查找dataSourceClass,如果找到,条件就成立。那么debug下,可以发现查找到的dataSourceClass是:org.apache.tomcat.jdbc.pool.DataSource 。

那么再看下org.apache.tomcat.jdbc.pool.DataSource这个类是从哪里来的呢?

从maven依赖树可以看到,依赖是来自:spring-boot-starter-jdbc。所以是应用依赖了spring-boot-starter-jdbc,但是并没有配置DataSource引起的问题。

问题解决办法

有两种:

  1. 没有使用到DataSource,则可以把spring-boot-starter-jdbc的依赖去掉,这样就不会触发spring boot相关的代码
  2. 把spring boot自动初始化DataSource相关的代码禁止掉

禁止的办法有两种:

  1. 在main函数上配置exclude


    @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class }) 

  2. 在application.properties里配置:


    spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration 

总结

  1. 应用没有使用到DataSource,但是在pom.xml里引入了spring-boot-starter-jdbc
  2. spring-boot-starter-jdbc带入了tomcat-jdbc,它里面有org.apache.tomcat.jdbc.pool.DataSource
  3. spring boot里的PooledDataSourceConfiguration,判断classpath下面有DataSource的实现类,尝试去创建DataSource bean
  4. 在初始化DataSourceProperties时,尝试通过jdbc的url来探测driver class
  5. 因为应用并没有配置url,所以最终在DataSourceProperties.determineDriverClassName()里抛出Cannot determine embedded database driver class for database type NONE

最后:

  • 排查spring boot的AutoConfiguration问题时,可以按异常栈,一层层排查Configuration是怎么引入的,再排查Condition具体的判断代码。

深入Spring Boot:怎样排查 Cannot determine embedded database driver class for database type NONE的更多相关文章

  1. 【spring cloud】【spring boot】项目启动报错:Cannot determine embedded database driver class for database type NONE

    解决参考文章:https://blog.csdn.net/hengyunabc/article/details/78762097 spring boot启动报错如下: Error starting A ...

  2. Spring boot出现Cannot determine embedded database driver class for database type NONE

    在spring boot项目中,我们在pom.xml文件中添加了mysql和mybatis的依赖,我们常常遇到下面这样的问题: Description: Cannot determine embedd ...

  3. Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embe

    Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationEx ...

  4. spriing boot 启动报错:Cannot determine embedded database driver class for database type NONE

    最近在学习使用spring boot.使用maven创建好工程,只引用需要用到的spring boot相关的jar包,除此之外没有任何的配置. 写了一个最简单的例子,如下所示: package com ...

  5. 解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE

    问题 如下: 2017-07-16 08:50:57.436  INFO 13524 --- [           main] c.p.p.web.PointshopWebApplication   ...

  6. 解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)

    问题 如下: 2017-07-16 08:50:57.436  INFO 13524 --- [           main] c.p.p.web.PointshopWebApplication   ...

  7. Eureka 客户端启动报错误 Cannot determine embedded database driver class for database type NONE

    用这种数据库配置就是死活连不上数据库 提示:Cannot determine embedded database driver class for database type NONE 解决方式: 启 ...

  8. Springboot项目启动报错,提示Cannot determine embedded database driver class for database type NONE

    我在springboot项目里面引入了数据库的配置: <dependency> <groupId>org.mybatis.spring.boot</groupId> ...

  9. SpringBoot项目报错Cannot determine embedded database driver class for database type NONE

    原因: Cannot determine embedded database driver class for database type NONE 这是因为spring boot默认会加载org.s ...

随机推荐

  1. linux 自总结常用命令(centos系统)

    查看apache2的命令 httpd -V 其中HTTPD_ROOT和SERVER_CONFIG_FILE  就可以确定httpd.conf(Apache配置文件)的路径了 apache启动.停止.重 ...

  2. PHP实现IP访问限制及提交次数的方法详解

    一.原理 提交次数是肯定要往数据库里写次数这个数据的,比如用户登陆,当用户出错时就忘数据库写入出错次数1,并且出错时间,再出错写2,当满比如5次时提示不允许再登陆,请明天再试,然后用DateDiff计 ...

  3. ELK-head

    Head从elastic5开始只是支持单独服务器,不能够在通过 elasticsearch/bin/plugin -install mobz/elasticsearch-head 这样简单的方式安装插 ...

  4. 语义分析之ansj_seg+word2vec的使用

    语义分析,我是一个初学者,有很多东西,需要理论和实践结合后,才能理解的相对清楚. 今天,我就在语义理解中基于背景语料的情况,实现语义上下文的预测,比如,我说“王宝强”,你会想到什么?别告诉没有“马蓉” ...

  5. 开源数据采集组件比较: scribe、chukwa、kafka、flume

    针对每天TB级的数据采集,一般而言,这些系统需要具有以下特征: 构建应用系统和分析系统的桥梁,并将它们之间的关联解耦: 支持近实时的在线分析系统和类似于Hadoop之类的离线分析系统: 具有高可扩展性 ...

  6. 转---CentOS安装Oracle数据库详细介绍及常见问题汇总

    一.安装前准备 1.软件硬件要求 操作系统:CentOS 6.4(32bit)Oracle数据库版本:Oracle 10g(10201_database_linux32.zip)最小内存:1G(检查命 ...

  7. sql server 安装时提示要重启

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager 打开“Session Manager”文件夹之后在右侧的区域中单 ...

  8. 《亲测》nginx webscoket ssl conf配置示例

    非crt证书,用的pem,其中 http://localhost:5003 是你要转发到的站点网址 配置的就是 server { listen 80; server_name smarthome.yi ...

  9. 【java】之彻底明白进制转换

    首先区分 2进制  只有0和1组成    如:0101018进制  以0开头,0~7组成   如:01234510进制 以1~9开头,0~9组成      如:10016进制 以0X开头,0~9或者a ...

  10. gitlab ssh clone问题解决

    公司搭建的gitlab,通过http协议可以clone: [sisi@pre-srv24 gitlab]$ git clone http://gitlab.test.mycompany.com/dev ...