DATACMNS-1373 - Use ReflectUtils.defineClass(…) to load generated EntityInstantiators.

We now use Spring's ReflectUtils.defineClass(…) to load generated EntityInstantiators which uses internally either MethodHandles.Lookup.defineClass(…) (on Java 9 and higher) or reflective defineClass invocation on the originating ClassLoader. Class injection into the originating ClassLoader assigns the ClassLoader of the entity to the generated class which allows optimized instantiation of package-protected classes and constructors.

Original pull request: #308.
This commit is contained in:
Mark Paluch
2018-08-17 11:19:31 +02:00
committed by Oliver Gierke
parent b0eb0c47d2
commit 9478441dbd
2 changed files with 89 additions and 48 deletions

View File

@@ -303,6 +303,66 @@ public class ClassGeneratingEntityInstantiatorUnitTests<P extends PersistentProp
});
}
@Test // DATACMNS-1373
public void shouldInstantiateProtectedInnerClass() {
prepareMocks(ProtectedInnerClass.class);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isFalse();
assertThat(this.instance.createInstance(entity, provider)).isInstanceOf(ProtectedInnerClass.class);
}
@Test // DATACMNS-1373
public void shouldInstantiatePackagePrivateInnerClass() {
prepareMocks(PackagePrivateInnerClass.class);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isFalse();
assertThat(this.instance.createInstance(entity, provider)).isInstanceOf(PackagePrivateInnerClass.class);
}
@Test // DATACMNS-1373
public void shouldNotInstantiatePrivateInnerClass() {
prepareMocks(PrivateInnerClass.class);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isTrue();
}
@Test // DATACMNS-1373
public void shouldInstantiateClassWithPackagePrivateConstructor() {
prepareMocks(ClassWithPackagePrivateConstructor.class);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isFalse();
assertThat(this.instance.createInstance(entity, provider)).isInstanceOf(ClassWithPackagePrivateConstructor.class);
}
@Test // DATACMNS-1373
public void shouldInstantiateClassInDefaultPackage() throws ClassNotFoundException {
Class<?> typeInDefaultPackage = Class.forName("TypeInDefaultPackage");
prepareMocks(typeInDefaultPackage);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isFalse();
assertThat(this.instance.createInstance(entity, provider)).isInstanceOf(typeInDefaultPackage);
}
@Test // DATACMNS-1373
public void shouldNotInstantiateClassWithPrivateConstructor() {
prepareMocks(ClassWithPrivateConstructor.class);
assertThat(this.instance.shouldUseReflectionEntityInstantiator(entity)).isTrue();
}
private void prepareMocks(Class<?> type) {
doReturn(type).when(entity).getType();
doReturn(PreferredConstructorDiscoverer.discover(type))//
.when(entity).getPersistenceConstructor();
}
static class Foo {
Foo(String foo) {
@@ -424,4 +484,21 @@ public class ClassGeneratingEntityInstantiatorUnitTests<P extends PersistentProp
this.param7 = param7;
}
}
protected static class ProtectedInnerClass {}
static class PackagePrivateInnerClass {}
private static class PrivateInnerClass {}
static class ClassWithPrivateConstructor {
private ClassWithPrivateConstructor() {}
}
static class ClassWithPackagePrivateConstructor {
ClassWithPackagePrivateConstructor() {}
}
}