Spring异常分析

异常报错


2019-01-14 10:40:18.427 ERROR 11776 --- [ost-startStop-1] o.s.b.w.e.t.TomcatStarter                : Error starting Tomcat context. 

Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'servletEndpointRegistrar' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration.class]:

Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:

Failed to instantiate [org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar]:

Factory method 'servletEndpointRegistrar' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'healthEndpoint' defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.actuate.health.HealthEndpoint]: Factory method 'healthEndpoint' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorAutoConfiguration':
Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException:

Failed to instantiate [org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorAutoConfiguration$$EnhancerBySpringCGLIB$$caa88ea6]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException:

Error creating bean with name 'dataSource': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]:

Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class

关键在最后一句Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class

我这里是有配置mysql驱动的。所以定位应该是配置问题。

根据提示,可以看出是从DataSourceProperties这里抛出来的异常。读取spring.datasource开头的配置项。如果spring.datasource.driverClassName为空,会抛出异常,提示Failed to determine a suitable driver class

我的配置文件里是有配置的,该配置在读取时会将driver-class-name转换为驼峰式写法driverClassName。所以问题应该是Springboot没有加载application.properties的问题,可以来验证一下。

启动后,异常信息变成

Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine suitable jdbc url

spring.datasource.driver-class-name=com.mysql.jdbc.Driver

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">determineDriverClassName</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">if</span> (StringUtils.hasText(<span class="hljs-keyword">this</span>.driverClassName)) {
        Assert.state(driverClassIsLoadable(),
                () -&gt; <span class="hljs-string">"Cannot load driver class: "</span> + <span class="hljs-keyword">this</span>.driverClassName);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.driverClassName;
    }
    String driverClassName = <span class="hljs-keyword">null</span>;
    <span class="hljs-keyword">if</span> (StringUtils.hasText(<span class="hljs-keyword">this</span>.url)) {
        driverClassName = DatabaseDriver.fromJdbcUrl(<span class="hljs-keyword">this</span>.url).getDriverClassName();
    }
    <span class="hljs-keyword">if</span> (!StringUtils.hasText(driverClassName)) {
        driverClassName = <span class="hljs-keyword">this</span>.embeddedDatabaseConnection.getDriverClassName();
    }
    <span class="hljs-keyword">if</span> (!StringUtils.hasText(driverClassName)) {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> DataSourceBeanCreationException(
                <span class="hljs-string">"Failed to determine a suitable driver class"</span>, <span class="hljs-keyword">this</span>,
                <span class="hljs-keyword">this</span>.embeddedDatabaseConnection);
    }
    <span class="hljs-keyword">return</span> driverClassName;
}

}

测试加载的配置文件


public class KzfApiAlipayApplication {

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
    ConfigurableApplicationContext context = SpringApplication.run(KzfApiAlipayApplication.class, args);
    System.out.println(context.getEnvironment().getProperty(<span class="hljs-string">"spring.datasource.driver-class-name"</span>));
}

}



public class ServletEndpointManagementContextConfiguration {

        @Configuration
    @ConditionalOnClass(DispatcherServlet.class)
    public static class WebMvcServletEndpointManagementContextConfiguration {

        private final ApplicationContext context;

        public WebMvcServletEndpointManagementContextConfiguration(
                ApplicationContext context) {
            this.context = context;
        }

        @Bean
        public ServletEndpointRegistrar servletEndpointRegistrar(
                WebEndpointProperties properties,
                ServletEndpointsSupplier servletEndpointsSupplier) {
            DispatcherServletPath dispatcherServletPath = this.context
                    .getBean(DispatcherServletPath.class);
            return new ServletEndpointRegistrar(
                    dispatcherServletPath.getRelativePath(properties.getBasePath()),
                    servletEndpointsSupplier.getEndpoints());
        }

    }

}

SpringBoot启动过程


@SpringBootApplication
public class CrawlerDiscreditApplication {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

    SpringApplication.run(CrawlerDiscreditApplication.class, args);

}

}

SpringApplication类


public class SpringApplication {
    <span class="hljs-keyword">private</span> ResourceLoader resourceLoader;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringApplication</span><span class="hljs-params">(Class&lt;?&gt;... primarySources)</span> </span>{
    <span class="hljs-keyword">this</span>(<span class="hljs-keyword">null</span>, primarySources);
}

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringApplication</span><span class="hljs-params">(ResourceLoader resourceLoader, Class&lt;?&gt;... primarySources)</span> </span>{
    <span class="hljs-keyword">this</span>.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, <span class="hljs-string">"PrimarySources must not be null"</span>);
    <span class="hljs-keyword">this</span>.primarySources = <span class="hljs-keyword">new</span> LinkedHashSet&lt;&gt;(Arrays.asList(primarySources));
    <span class="hljs-keyword">this</span>.webApplicationType = deduceWebApplicationType();
    setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    <span class="hljs-keyword">this</span>.mainApplicationClass = deduceMainApplicationClass();
}

}

原文地址:https://www.cnblogs.com/jpfss/p/11308439.html