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

最新文章

  1. KnockoutJS 3.X API 第八章 映射(mapping)插件
  2. eclipse 导入工程报错Unable to execute dex: Multiple dex files define Landroid/annotation/SuppressLint
  3. jsp前三章小测试:错题
  4. 解决WordPress中无法将上传的文件移动至wp-content/uploads
  5. EXCEL VBA入门篇之代码应用基础
  6. Java基础之创建窗口——使窗口在屏幕居中(TryWindow2/TryWindow3)
  7. 初始化ArrayList的两种方法
  8. hbase日常操作及维护
  9. proxy server 代理服务器
  10. POJ 2251 三维BFS(基础题)
  11. jQuery中的常用内容总结(二)
  12. ProgressDialog的使用及逻辑处理
  13. iOS开发点滴-添加阴影效果
  14. ArcGIS API for JavaScript 4.x 本地部署之Apache(含Apache官方下载方法)
  15. linux下安装nodejs及npm
  16. Graphics Class
  17. mvc开发网站打开慢总结
  18. DOM操作 JS事件 节点增删改查
  19. Pandas分组统计函数:groupby、pivot_table及crosstab
  20. Keras之inception_v3使用

热门文章

  1. 未来科技城 x 奇点云打造「企业数据大脑」,助力1.3万家企业服务
  2. RxJava操作符实践:8_算术和聚合操作之3_min
  3. 吴裕雄--天生自然HTML学习笔记:HTML 属性
  4. 吴裕雄--天生自然 R语言开发学习:时间序列(续三)
  5. java MVC 自定义类型转换器(Formatter、AnnotationFormatterFactory)
  6. python标准库-calendar 模块
  7. 吴裕雄--天生自然KITTEN编程:滂沱大雨
  8. Java 关于线程的面试题及答案
  9. TCP大文件发送案例以及UDP介绍
  10. Swift 进阶 第 4 课 集合类型协议