SpringBoot项目,引了一个内部的工具包,竟然导致启动失败,报找不到freemarker Configuration类的一个属性,网上的解法都大同小异,最终用了自己的办法解决,花点时间记录下来,希望能帮助到别人。

关键词:SpringBoot,AutoConfiguration,freemarker,NoSuchFiledError

问题背景

最近在开发过程中由于要用到公司内部的一个工具类,所以添加了common-util.jar到工程的maven依赖中,功能开发完了,打算本地调试一下,但悲剧的是应用启动失败了。查看堆栈信息,并没有我新添加的代码,是Spring初始化失败了,堆栈信息如下:

初步分析

对照着堆栈来看,错误很明确,就是在运行时缺少freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS 这个field导致,但是怎么解决呢?度娘上基本都是下面这两种解决办法:

图片来源于https://www.cnblogs.com/geekdc/p/9243069.html

我并没有采用这两种办法,因为这并不是一个新搭建的工程,而且我这次也没有做过任何版本升级,唯一的可能就是引入的新jar包有问题。

再看异常堆栈

从堆栈来看是缺少了一个Field导致,那什么情况下会造成这种情况呢,我第一时间猜测应该是jar包冲突了,因为之前遇到过一次,有兴趣的可以看这里,我查看了新引入jar包内部的pom文件,确实是依赖了freemarker(2.3.16)的jar包,而且scope是compile,就这样,这个低版本的freemarker被传递依赖进来了,至于最终使用哪个,就由maven的仲裁机制决定了,很明显我这个工程最终用了老版本,所以导致运行时找不到Field,解决方案很简单,使用exclusion将老版本的freemarker排除就好了。一般故事到这儿就结束了,但是我这个人手贱,偏要看看项目以前依赖的freemarker是什么版本的,结果看完又不能按时睡觉了(题外话:白天老是这事那事,晚上才有时间写代码)。

意外收获

我使用mvn dependency:tree将所有依赖都输出到文本文件里,然后搜索freemarker,结果意外的发现居然没有依赖freemarker,这是什么情况,刚刚不是还j说ar包冲突了吗,难道是自我冲突了?

一时间没有了头绪,想百度都不知道关键字写什么。一般这个时候我会点根烟开始复盘,从头到尾反复看案发现场,总能发现蛛丝马迹。终于灵光一下,我脑子里闪过这么一段话“之前没有freemarker.jar的时候不报错,现在有了也应该不报错才对,除非SpringBoot具有自动发现功能,可以实现组件可插拔”,就这样,我尝试搜索“SpringBoot自动发现”,看看百度给我的结果:

我很自然的过滤了第二条搜索内容,因为我知道那不是我想要的,我内心想表述的其实是“自动转配、自动配置”。

根因分析

了解了自动装配的大概原理后,我梳理出了这次启动失败的根本原因,如下:

  1. SpringBoot启动的时候触发自动配置;
  2. spring-boot-autoconfigure-1.5.11.RELEASE.jar\META-INF\spring.factories里面是需要自动配置的Bean,里面就有FreeMarkerAutoConfiguration;
  3. 自动配置一般会有一些约束条件,满足条件才会自动配置,条件通过@Condition***这类注解来声明;
  4. FreeMarkerAutoConfiguration的自动配置约束条件为@ConditionalOnClass({freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class}),意味着只有freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class这两个类都存在的时候才会自动配置;
  5. 如果第四步满足条件,最终会触发FreeMarkerConfigurationFactory.newConfiguration这个方法,这个方法内部用到了Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS这个Field,它来源于freemarker.jar,就是堆栈中报NoSuchFiledError的主角;
  6. 如果第四步不满足条件,就不触发FreeMarkerAutoConfiguration的自动配置,进而不会用到Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS这个Field;

FreeMarkerConfigurationFactory来源于spring-context-support-4.3.15.RELEASE.jar,这个jar包之前就依赖了,而Configuration来源于freemarker.jar,是common-util.jar传递依赖进来的,所以正好满足了上面的第四步,进而触发了第五步,最终导致SpringBoot启动失败。

汇总解决办法

通过上面的一些分析,我认为这个问题一共有以下几种办法:

  1. 如果你的项目中没有用到freemarker的话可以禁用freemarker的自动配置,像初步分析那里提到的;
  2. 升级freemarker到高版本;
  3. 像我遇到的问题一样,确实不需要freemarker功能,可以将freemarker.jar排除;

总结

虽然是个很小的问题,但是解决过程确实让我收获不少,之前对于SpringBoot只停留在简单使用阶段,通过这次排查过程,也算是了解了SpringBoot自动配置的大体思想,这种可插拔的设计真的是非常巧妙。

如果觉得有用,请您点个推荐。

参考资料:

https://www.cnblogs.com/nijunyang/p/12051770.html

https://blog.csdn.net/ZYC88888/article/details/84245127

SpringBoot突报java.lang.NoSuchFieldError分析的更多相关文章

  1. springboot启动异常java.lang.NoSuchFieldError: DEFAULT_INCOMPATIBLE_IMPROVEMENTS

    解决办法一 yml或者Properties文件中配置 spring.freemarker.check-template-location=false 解决办法二 @SpringBootApplicat ...

  2. 【原创】大叔问题定位分享(2)spark任务一定几率报错java.lang.NoSuchFieldError: HIVE_MOVE_FILES_THREAD_COUNT

    最近用yarn cluster方式提交spark任务时,有时会报错,报错几率是40%,报错如下: 18/03/15 21:50:36 116 ERROR ApplicationMaster91: Us ...

  3. java.lang.NoSuchFieldError: VERSION_2_3_0 报错解决方案

    java.lang.NoSuchFieldError: VERSION_2_3_0 at org.apache.struts2.views.freemarker.FreemarkerManager.c ...

  4. springBoot集成Elasticsearch抛出Factory method 'restHighLevelClient' threw exception; nested exception is java.lang.NoSuchFieldError: IGNORE_DEPRECATIONS

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restHighLeve ...

  5. jenkins执行构建任务报错之java.lang.NoSuchFieldError: DEFAULT_USER_SETTINGS_FILE

    在执行创建工作空间时候,创建不成功,出现错误?? ......... java.lang.NoSuchFieldError: DEFAULT_USER_SETTINGS_FILE ......... ...

  6. java报错:Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE

    Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE at org.apache.http.conn.ss ...

  7. java.lang.NoSuchFieldError 异常原因

    一般都是因为 class 或 jar 包重复 导致的 , 也有可能是编译器的问题. 我碰到的问题是,在项目api 接口jar包里定义了一个Config.java,然后在业务层service 项目 的相 ...

  8. Java.lang.NoSuchFieldError: INSTANCE异常

    解决方案: java.lang.NoSuchFieldError: INSTANCE异常. 1.jar包重复了. 2.版本还不相同,如果包的版本不同也会报相应的错,不过一般情况自己导入的jar包主要看 ...

  9. java.lang.NoSuchFieldError: RAW_XML_FILE_HEADER,调用XWPFTemplate动态合并生成一个新的docx文档时报错

    在使用 org.apache.poi 对office文件  根据表单内容和已上次的附件 动态合并成一个新的文档时,本地调试完全ok 但是发布倒Linux环境上就老是报这个错误java.lang.NoS ...

随机推荐

  1. java通过jdbc插入中文到mysql显示乱码(问号或者乱码)

    对于很多初学者来说,中文字符编码不相同的问题,是一个很烦躁的问题!! 因为很多时候,我们并不知道,到底是哪一层出现了问题? 在这里稍微做个总结~也怕自己今后忘了!! 其实也就三层: 1.前端页面 2. ...

  2. js正则表达式常用的大部分函数

    1.)String方法a.)String.search()参数:可以是正则表达式也可以是普通的字符串.返回值:如果找到匹配则返回首字符的索引位置,找不到则返回-1var s = "Hello ...

  3. particlesJS is not defined

    插件或者js文件在引入时需要注意引入顺序,每次都找很久的错误 一般引入min.js就可以,min.js意思就是压缩的js文件 引入时应该先加入min类的文件在引入配置文件 比如particles插件, ...

  4. 洛谷-P3809-后缀排序(后缀数组)

    看了求后缀数组的倍增法之后很快就理解了,但是自己写的倍增法用map排序还是超时了.然后看了两天别人写的模板,题目是通过了,但感觉代码还是半懂半背的.以后多熟悉熟悉吧: 后缀数组 #include &q ...

  5. 转:B树和B+树的插入、删除图文详解

    如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. B树 1. B树的定义 B树也称B-树,它是一颗多路平衡查找树.我们描述一颗B树时需要指定它的阶数,阶数表示了 ...

  6. python标准库-calendar 模块

    原文地址:http://www.bugingcode.com/blog/python_calendar.html calendar 模块是python实现的unix 的 cal命令.它可以以标准的模式 ...

  7. ltp压力测试结果分析脚本

    最近工作性质发生了改变,在做操作系统方面的测试.接手的第一个任务是做ltp stress.测试内核稳定性. 做完之后会结果进行统计分析.因为统计的内容比较多,都是通过shell命令行进行操作.于是编写 ...

  8. MyBatis之pageHelper分页插件

    1.先导入Maven,jar包依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifa ...

  9. ubuntu 16 下安装 Ubuntu Make

    第一步:下载安装包 地址:http://ftp.gnu.org/gnu/make/ 第二步:解压 先进入存放文件目录,图示: 进行解压,图示: 解压并copy到安装目录 第三步:编译 1.查看目录, ...

  10. Flutter混合开发:Android接入Flutter

    Flutter Google推出已经已经一年多了,单个 Flutter 项目的开发流程已经很成熟了.对与个人开发者来说使用 Flutter 开发一个跨平台的App挺有意思.但是对于现有的项目改造来说还 ...