使用了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
相關文章
相關標籤/搜索