一个spring boot程序的启动报错问题: Unable to read meta-data for class

1. 问题描述

Spring Boot Application在启动时报如下错误,

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.8.RELEASE)

 ...
 2018-08-02 10:46:59.333  WARN 12168 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.pphh.oauth.sample.App]; nested exception is java.lang.IllegalStateException: Unable to read meta-data for class  com.pphh.oauth.config.FilterAutoConfiguration

 org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.pphh.oauth.sample.App]; nested exception is java.lang.IllegalStateException: Unable to read meta-data for class  com.pphh.oauth.config.FilterAutoConfiguration

 Caused by: java.lang.IllegalStateException: Unable to read meta-data for class  com.pphh.oauth.config.FilterAutoConfiguration
     at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getAnnotationMetadata(AutoConfigurationSorter.java:217) ~[spring-boot-autoconfigure-1.5.8.RELEASE.jar:1.5.8.RELEASE]
     ... 14 common frames omitted
 Caused by: java.io.FileNotFoundException: class path resource [ com/pphh/oauth/config/FilterAutoConfiguration.class] cannot be opened because it does not exist
     at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172) ~[spring-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
     ... 22 common frames omitted

 Disconnected from the target VM, address: '127.0.0.1:64322', transport: 'socket'

 Process finished with exit code 1

2. 问题查看和解决

错误消息中告知无法找到com/pphh/oauth/config/FilterAutoConfiguration.class这个class。但是,这个依赖包肯定是加载进来了,这个类也一定有,但是为什么找不到?

先看异常抛出的地方,

org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)

执行的代码如下,

InputStream is;
if(this.clazz != null) {
    is = this.clazz.getResourceAsStream(this.path);
} else if(this.classLoader != null) {
    is = this.classLoader.getResourceAsStream(this.path);
} else {
    is = ClassLoader.getSystemResourceAsStream(this.path);
}

if(is == null) {
    throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
} else {
    return is;
}

可以看到,原因就是无法加载类文件,这里设置一个断点,准备调试看下。

在调试模式中,进入上面的执行代码,发现确实is加载后为null。我觉得很奇怪,类明明在class加载路径上,怎么为null。于是我在调试框手动执行类加载,

ClassLoader.getSystemResourceAsStream("com/pphh/oauth/config/FilterAutoConfiguration.class");

上面的手动执行能够正确加载。

最后比较了下两次ClassLoader命令的文件路径,发现了问题,this.path所指向的class path resource路径前面有一个空格。

  • 错误的class path resource [ com/pphh/oauth/config/..Configuration.class]
  • 正常的class path resource [com/pphh/oauth/config/..Configuration.class]

然后定位问题到相应的spring.factories配置文件中,

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pphh.oauth.config.ClientAutoConfiguration, \
com.pphh.oauth.config.FilterAutoConfiguration

将其更新为,

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pphh.oauth.config.ClientAutoConfiguration,\
com.pphh.oauth.config.FilterAutoConfiguration

问题得到解决,此记以参考。

3. 后记

很多时候,代码没有问题,却由于配置出错导致应用启动失败,这种问题非常多,防不胜防,也是比较头疼的问题。多加细心,同时对于配置问题的容错报错,也有助于问题的解决。

就以上面的例子,spring boot在加载auto configuration类之前,若能够自动去掉类名的前后空格,就不会导致上述问题。毕竟,在编写spring.factories的时候,很难确保不人为的添加空格。

发表评论

电子邮件地址不会被公开。 必填项已用*标注