我在Play 2.4.2 (最新版本)框架应用程序中使用ModelMapper 0.7.4 (最新版本)。Play 2.4有一个内置的Google依赖项注入解决方案,我们的应用程序是从Guice手动连接到Spring框架依赖注入解决方案,以使Play 2.4与Spring一起工作。所以沟通从游戏到Guice再到春天。
东西(Spring中的依赖注入)似乎工作得很好,但是当测试开发环境中随机的Java类发生变化时,Play会自动重新加载类或webapp。这种重新加载通常可以很好地工作,但是当在这个播放设置中使用ModelMapper作为Spring时,它似乎会给ModelMapper带来问题。(但当绕过Guice桥时,无法重现问题,方法是在安装过程中手动创建Spring容器,然后将ModelMapper作为Spring联系。)
错误是:
Caused by: org.modelmapper.ConfigurationException: ModelMapper configuration errors:
1) Failed to configure mappings
1 error
at org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:241) ~[modelmapper-0.7.4.jar:na]
at org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:207) ~[modelmapper-0.7.4.jar:na]
at org.modelmapper.internal.TypeMapImpl.addMappings(TypeMapImpl.java:72) ~[modelmapper-0.7.4.jar:na]
at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:101) ~[modelmapper-0.7.4.jar:na]
at org.modelmapper.ModelMapper.addMappings(ModelMapper.java:93) ~[modelmapper-0.7.4.jar:na]
at configs.AppConfig.modelMapper(AppConfig.java:109) ~[na:na]
at configs.AppConfig$$EnhancerBySpringCGLIB$$b19a8688.CGLIB$modelMapper$2(<generated>) ~[na:na]
at configs.AppConfig$$EnhancerBySpringCGLIB$$b19a8688$$FastClassBySpringCGLIB$$1f1c1728.invoke(<generated>) ~[na:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318) ~[spring-context-4.2.0.RELEASE.jar:4.2.0.RELEASE]
at configs.AppConfig$$EnhancerBySpringCGLIB$$b19a8688.modelMapper(<generated>) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_45]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
... 64 common frames omitted
Caused by: java.lang.ClassCastException: project.entities.User$$EnhancerByModelMapper$$f1b8f0f9 cannot be cast to project.entities.User
at configs.AppConfig$1.configure(AppConfig.java:106) ~[na:na]
at org.modelmapper.PropertyMap.configure(PropertyMap.java:383) ~[modelmapper-0.7.4.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_45]
at org.modelmapper.internal.ExplicitMappingBuilder.build(ExplicitMappingBuilder.java:195) ~[modelmapper-0.7.4.jar:na]
... 78 common frames omitted这种情况只发生在类重新加载时,而不是在没有重新加载的情况下。此外,当不使用modelMapper.addMappings(aPropertyMap)时,不会出现此问题。Spring AppConfig类如下所示:
@Configuration
public class AppConfig {
@Bean
public ModelMapper modelMapper() {
ModelMapper modelMapper = new ModelMapper();
// BEGIN: WITHOUT THE FOLLWOING CODE, it works fine
PropertyMap<CreateUserFormDTO, User> userMap = new PropertyMap<CreateUserFormDTO, User>() {
@Override
public void configure() {
map().setPassword(source.getPassword1());
}
};
modelMapper.addMappings(userMap);
// END
return modelMapper;
}
}可以使用普通的Spring @Autowire注入来访问ModelMapper。用户和CreateUserFormDTO类只是POJO。
问题是什么?
发布于 2018-05-15 10:16:17
问题就在于简所说的。根据Spring工具:
每当类路径上的文件发生变化时,使用spring devtools的应用程序就会自动重新启动。在IDE中工作时,这可能是一个有用的特性,因为它为代码更改提供了一个非常快速的反馈循环。
当发生代码更改时,由于基本类加载器,ModelMapper库已经加载到类路径中。根据Spring工具:
Spring提供的重新启动技术通过使用两个类加载器来工作。不改变的类(例如,来自第三方jars的类)被加载到基本的类加载器中。您正在积极开发的类被加载到重新启动类加载器中。当应用程序重新启动时,将抛出重新启动类加载器,并创建一个新的类加载器。这种方法意味着应用程序重新启动通常比“冷启动”快得多,因为基本的类加载器已经可用并填充了。
默认情况下,IDE中任何打开的项目都会加载“重新启动”类加载器,而任何常规的.jar文件都会加载“基本”类加载器。
因此,我们需要自定义重新启动类加载器,并将modelmapper.jar放入重新启动类加载器中,而不是基类加载程序。
为了这样做,
META-INF/spring-devtools.properties文件,将其加载到项目的类路径中。链接:
发布于 2015-09-15 07:50:28
这里的问题是,ModelMapper创建映射器的内存缓存(参见TypeMapStore.getOrCreate ),并创建一个生成器类,该类返回与模型兼容的类(User$$EnhancerByModelMapper$$f1b8f0f9扩展User)。
只要你不重新装填,一切正常。但是,一旦重新加载play应用程序,app类加载器就会被丢弃,因此在新的类加载器中加载了User类的一个新实例。User$$EnhancerByModelMapper$$f1b8f0f9仍然扩展了以前的类,并且未能转换到新的类。
我没有使用ModelMapper的解决方案。我猜您必须修复ModelMapper,以便当缓存映射程序抛出一个ClassCastException时,TypeMapstore放弃它并尝试重新创建一个新的映射器。
最后,当我在ModelMapper上评论类加载问题时,我所从事的项目最终用Selma (http://www.selma-java.org/)代替了ModelMapper,后者在我们的测试中运行得很好(我的合同在那时终止了,我不知道他们最终是否保留了selma )。
https://stackoverflow.com/questions/32127438
复制相似问题