Spring boot devtools 加载两次 class 并导致 LinkageError

Spring boot devtools load twice of a class and cause LinkageError

IDE是Idea,Spring引导工程有META-INF/spring-devtools.properties,内容是

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

当 运行 项目抛出以下异常时

2015-12-03 12:02:49,491 [restartedMain] INFO  org.dozer.DozerBeanMapper - Initializing a new instance of dozer bean mapper.
2015-12-03 12:02:49,494 [restartedMain] WARN  o.s.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dozerBeanMapper' defined in class path resource [com/foo/common/CommonConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.dozer.Mapper]: Factory method 'dozerBeanMapper' threw exception; nested exception is 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"
2015-12-03 12:02:49,517 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dozerBeanMapper' defined in class path resource [com/foo/common/CommonConfiguration.class]: Bean instantiation via factory method failed; nested exception is    org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.dozer.Mapper]: Factory method 'dozerBeanMapper' threw exception; nested exception is 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 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.2.3.RELEASE.jar:4.2.3.RELEASE]

奇怪的是运行在Eclipse中建工程时,没有上述问题。 在idea中添加-XX:+TraceClassLoading配置,发现dozer加载了两次

9569 [Loaded org.dozer.DozerBeanMapper from file:/C:/Users/otto/.m2/repository/net/sf/dozer/dozer/5.5.1/dozer-5.5.1.jar]

9618 [Loaded org.dozer.DozerBeanMapper from file:/C:/Users/otto/.m2/repository/net/sf/dozer/dozer/5.5.1/dozer-5.5.1.jar]

现在不知道怎么定位这个问题的原因?

您共享的项目的自述文件中有一些关键信息未包含在问题中:

Download sample project then import this project to eclipse, closed bar project then run FooApplication you could get below error

关闭酒吧项目意味着其 classes 将不符合重新启动的条件。这意味着它们将由主 class 加载程序而不是重新启动 class 加载程序加载。 bar 中的代码依赖于 Dozer,但是你已经配置了 DevTools,这样 Dozer 的 classes 将在重启时加载 class loader:

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

我不清楚你为什么要这样配置。如果我删除 spring-devtools.properties,您的样本对我来说工作正常。也许示例没有说明导致您应用该配置的问题?

如果您确实需要此配置并且您不想在 Eclipse 中打开 bar 项目,那么您还需要配置 bar 以包含在重新启动中,以便它和它所依赖的 Dozer 都被加载重启 class 加载程序:

restart.include.dozer=/dozer-5\.5\.1\.jar
restart.include.bar=/bar-1\.0-SNAPSHOT\.jar