使用了Spring boot devtools, dozer转换嵌套对象失败解决记录

业务背景:html

添加商品以及价格,一个商品会有多个价格(针对不一样用户等级).java

代码:spring

先在controller中使用dozer将goodsForm-->Goods,而后保存商品, 以后遍历商品价格列表,注入商品ID,接着保存商品价格.app

GoodsForm:
List<GoodsPriceForm> priceList;
Goods:
List<GoodsPrice> priceList;

Controller:
Goods goods = BeanMapper.map(goodsForm, Goods.class);
save(goods);
goods.getPriceList().forEach(p->p.setGoodsId(goods.getId()));
save(goods.getPriceList());

在遍历商品价格列表时报错, 错误信息:spring-boot

java.lang.ClassCastException: com.foo.goods.model.GoodsPrice cannot be cast to com.foo.goods.model.GoodsPrice
at com.foo.goods.service.GoodsService$$Lambda$11/310447431.accept(Unknown Source) ~[na:na]
at java.util.ArrayList.forEach(ArrayList.java:1249) ~[na:1.8.0_51]
at com.foo.goods.service.GoodsService.saveGoods(GoodsService.java:34) ~[classes/:na]

对这一异常描述有些摸不着头脑, 经提醒有多是不一样的类加载器加载致使, 在Eclipse debug模式中Expression视图下,输出了goods和goodsPrice的类加载器名this

Goods: org.springframework.boot.devtools.restart.classloader.RestartClassLoader@41aa15ea
GoodsPrice:  sun.misc.Launcher$AppClassLoader@58644d46

果真涉及到不一样的类加载器. spa

尝试了在pom.xml中注释掉spring-boot-devtools, 再启动后没有上述异常. 但如何在保留devtools的状况下解决该问题呢? 查询官方文档:debug

By default, any open project in your IDE will be loaded using the “restart” classloader, and any regular .jar file will be loaded using the “base” classloader. If you work on a multi-module project, and not each module is imported into your IDE, you may need to customize things. To do this you can create aMETA-INF/spring-devtools.properties file.rest

The spring-devtools.properties file can contain restart.exclude. and restart.include. prefixed properties. The include elements are items that should be pulled-up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that will be applied to the classpath.code

因而在工程的resources目录下添加了META-INF/spring-devtools.properties,内容为

restart.include.dozer=/dozer-5.5.1.jar

即dozer代码也使用RestartClassLoader,能够解决上述问题.

补充:

在该工程中的Application类中有以下一段代码

  @Bean
  public Mapper fooDozerBeanMapper() {
    DozerBeanMapper mapper = BeanMapper.getDozerBeanMapper();
    List<String> mappingFiles = Lists.newArrayList(mapper.getMappingFiles());
    mappingFiles.add("foo-dozer-custom-convert.xml");
    mapper.setMappingFiles(mappingFiles);
    return mapper;
  }

其中BeanMapper是依赖另外一个工程(bar), 当在Eclipse中关闭该依赖工程(bar)后, 会报错

Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of org/springframework/boot/devtools/restart/classloader/RestartClassLoader) previously initiated loading for a different type with name "org/dozer/DozerBeanMapper"
	at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_05]
	at java.lang.ClassLoader.defineClass(ClassLoader.java:760) ~[na:1.8.0_05]
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_05]

解决方法

修改spring-devtools.properties,再增长一个配置

restart.include.bar=/bar.jar
restart.include.dozer=/dozer-5.5.1.jar
相关文章
相关标签/搜索