ModelMapper中的ClassCastException:无法强制转换EnhancerByModelMapper [英] ClassCastException in ModelMapper: EnhancerByModelMapper cannot be cast

查看:134
本文介绍了ModelMapper中的ClassCastException:无法强制转换EnhancerByModelMapper的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Play 2.4.2(最新版本)框架应用程序中使用ModelMapper 0.7.4(最新版本). Play 2.4内置了内部Google Guice依赖项注入解决方案,我们的应用程序是从Guice手动桥接到Spring Framework依赖项注入解决方案的,以使Play 2.4与Spring一起使用.因此交流从Play到Guice再到Spring.

I'm using ModelMapper 0.7.4 (latest version) in a Play 2.4.2 (latest version) framework application. Play 2.4 has an internal Google Guice dependency injection solution build into it, and our application is a manually bridged from Guice to a Spring Framework dependency injection solution, to get Play 2.4 to work with Spring. So communication flows from Play to Guice to Spring.

事情(使用Spring进行依赖注入)似乎可以正常工作,但是当在测试开发环境中更改随机Java类时,Play会自动重新加载该类或webapp.通常,此重装工作正常,但当在此Play设置中将ModelMapper用作Spring Bean时,似乎会导致ModelMapper出现问题. (但是,通过在安装程序中手动创建一个Spring容器,然后将ModelMapper作为Spring bean来绕过Guice-Spring桥时,无法重现该问题.)

Things (dependency injection with Spring) seem to work fine, but when a random Java class is changed in the test development environment, Play automatically reloads the class or webapp. This reloading work fine in general, but it seems to cause problems with ModelMapper, when ModelMapper is used as a Spring Bean in this Play setup. (But couldn't reproduce the problem when bypassing the Guice-Spring bridge by manually creating a Spring container within the setup and then contacting ModelMapper as a Spring bean.)

错误是:

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类如下所示:

This only happens on a class reload, and not when no reloading is done. Also, the problem does NOT occur when modelMapper.addMappings(aPropertyMap) is not used. The Spring AppConfig class looks like this:

@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. User和CreateUserFormDTO类只是POJO.

The ModelMapper is accessed using a plain Spring @Autowire injection. The User and CreateUserFormDTO class are just POJOs.

可能是什么问题?

推荐答案

问题恰好是Jean所说的. 根据Spring-Dev Tools:

The problem is exactly what Jean said. According to Spring-Dev Tools:

只要类路径上的文件发生更改,使用spring-boot-devtools的应用程序就会自动重新启动.在IDE中工作时,这可能是一个有用的功能,因为它为代码更改提供了非常快速的反馈循环.

Applications that use spring-boot-devtools automatically restart whenever files on the classpath change. This can be a useful feature when working in an IDE, as it gives a very fast feedback loop for code changes.

发生代码更改时,由于基础类加载器,ModelMapper库已经被加载到类路径中.根据Spring-Dev工具:

When code change occurs, ModelMapper Library is already loaded into classpath due to base classloader. According to Spring-Dev tools:

Spring Boot提供的重启技术通过使用两个类加载器来工作.不变的类(例如,来自第三方jar的类)将被加载到基类加载器中.您正在积极开发的类将加载到重新启动类加载器中.重新启动应用程序后,将丢弃重新启动类加载器,并创建一个新的类加载器.这种方法意味着应用程序的重新启动通常比冷启动"要快得多,因为基本类加载器已经可用并已填充.

The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader. When the application is restarted, the restart classloader is thrown away and a new one is created. This approach means that application restarts are typically much faster than "cold starts", since the base classloader is already available and populated.

默认情况下,IDE中任何打开的项目都使用重新启动"类加载器加载,而任何常规的.jar文件都使用基本"类加载器加载.

By default, any open project in your IDE is loaded with the "restart" classloader, and any regular .jar file is loaded with the "base" classloader.

因此,我们需要自定义重新启动类加载器,并将modelmapper.jar放入重新启动类加载器,而不是基类加载器.

So, we need to customize the Restart Classloader and put modelmapper.jar into restart classloader instead of base classloader.

为此,

  1. 在项目中创建一个META-INF/spring-devtools.properties文件,以将其加载到项目的类路径中.

  1. Create a META-INF/spring-devtools.properties file in your project to load it into project's classpath.

在spring-devtools.properties文件中添加此行

add this line in spring-devtools.properties file

restart.include.modelmapper=/modelmapper-.*.jar

  • 清洁&建立完整的项目.现在,每次有文件更改时,都会始终重新加载modelmapper库.

  • Clean & Build the full project. Now modelmapper library will always be reloaded each time there is a file change.

    链接:

    1. ModelMapper问题:254
    2. 自定义重启类加载器
    1. ModelMapper Issue: 254
    2. Customizing the Restart Classloader

    这篇关于ModelMapper中的ClassCastException:无法强制转换EnhancerByModelMapper的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    相关文章
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆