diff --git a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java index 2c8022da1..11b04c496 100644 --- a/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java +++ b/src/main/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiator.java @@ -130,6 +130,13 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator { try { return doCreateEntityInstantiator(entity); } catch (Throwable ex) { + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug( + String.format("Cannot create entity instantiator for %s. Falling back to ReflectionEntityInstantiator.", + entity.getName()), + ex); + } return ReflectionEntityInstantiator.INSTANCE; } } @@ -376,12 +383,22 @@ class ClassGeneratingEntityInstantiator implements EntityInstantiator { @Nullable PreferredConstructor, ?> constructor) { String className = generateClassName(entity); + Class> type = entity.getType(); + ClassLoader classLoader = type.getClassLoader(); + + if (ClassUtils.isPresent(className, classLoader)) { + + try { + return ClassUtils.forName(className, classLoader); + } catch (Exception o_O) { + throw new IllegalStateException(o_O); + } + } + byte[] bytecode = generateBytecode(className, entity, constructor); - Class> type = entity.getType(); - try { - return ReflectUtils.defineClass(className, bytecode, type.getClassLoader(), type.getProtectionDomain(), type); + return ReflectUtils.defineClass(className, bytecode, classLoader, type.getProtectionDomain(), type); } catch (Exception e) { throw new IllegalStateException(e); } diff --git a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java index 00f82f88d..de5e139a9 100755 --- a/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/ClassGeneratingEntityInstantiatorUnitTests.java @@ -23,6 +23,7 @@ import static org.springframework.data.util.ClassTypeInformation.from; import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; @@ -40,6 +41,8 @@ import org.springframework.data.mapping.PreferredConstructor.Parameter; import org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.ObjectInstantiator; import org.springframework.data.mapping.model.ClassGeneratingEntityInstantiatorUnitTests.Outer.Inner; import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.ReflectionUtils; /** @@ -211,6 +214,9 @@ class ClassGeneratingEntityInstantiatorUnitTests
assertThat(instance).isInstanceOf(ObjCtorNoArgs.class); assertThat(((ObjCtorNoArgs) instance).ctorInvoked).isTrue(); }); + + ClassGeneratingEntityInstantiator classGeneratingEntityInstantiator = new ClassGeneratingEntityInstantiator(); + classGeneratingEntityInstantiator.createInstance(entity, provider); } @Test // DATACMNS-578, DATACMNS-1126 @@ -361,6 +367,26 @@ class ClassGeneratingEntityInstantiatorUnitTests
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isTrue();
}
+ @Test // GH-2446
+ void shouldReuseGeneratedClasses() {
+
+ prepareMocks(ProtectedInnerClass.class);
+
+ this.instance.createInstance(entity, provider);
+
+ ClassGeneratingEntityInstantiator instantiator = new ClassGeneratingEntityInstantiator();
+ instantiator.createInstance(entity, provider);
+
+ Map