Skip to content

Commit 1a45458

Browse files
committed
Polishing.
Add generic signature, skip static initializer if not required, access classes in static initializer through constants instead of using forName(…). See #3365
1 parent 4c7a76a commit 1a45458

File tree

1 file changed

+49
-30
lines changed

1 file changed

+49
-30
lines changed

src/main/java/org/springframework/data/mapping/model/ClassGeneratingPropertyAccessorFactory.java

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,22 @@ static Class<?> generateCustomAccessorClass(PersistentEntity<?, ?> entity) {
384384
static byte[] generateBytecode(String internalClassName, PersistentEntity<?, ?> entity) {
385385

386386
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
387-
cw.visit(Opcodes.V1_8, ACC_PUBLIC + ACC_SUPER, internalClassName, null, JAVA_LANG_OBJECT, IMPLEMENTED_INTERFACES);
387+
388+
String signature = referenceName(JAVA_LANG_OBJECT) + String.format("L%s<%s>;",
389+
Type.getInternalName(PersistentPropertyAccessor.class), referenceName(entity.getType()));
390+
391+
cw.visit(Opcodes.V1_8, ACC_PUBLIC + ACC_SUPER, internalClassName, signature, JAVA_LANG_OBJECT,
392+
IMPLEMENTED_INTERFACES);
388393

389394
List<PersistentProperty<?>> persistentProperties = getPersistentProperties(entity);
390395

391396
visitFields(entity, persistentProperties, cw);
392397
visitDefaultConstructor(entity, internalClassName, cw);
393-
visitStaticInitializer(entity, persistentProperties, internalClassName, cw);
398+
399+
if (requiresMethodHandleSetup(entity, persistentProperties)) {
400+
visitStaticInitializer(entity, persistentProperties, internalClassName, cw);
401+
}
402+
394403
visitBeanGetter(entity, internalClassName, cw);
395404
visitSetProperty(entity, persistentProperties, internalClassName, cw);
396405
visitGetProperty(entity, persistentProperties, internalClassName, cw);
@@ -515,9 +524,7 @@ private static void visitDefaultConstructor(PersistentEntity<?, ?> entity, Strin
515524
* Method getter;
516525
* Method setter;
517526
* MethodHandles.Lookup lookup = MethodHandles.lookup();
518-
* Class class_1 = Class.forName("org.springframework.data.mapping.Person");
519-
* Class class_2 = Class.forName("org.springframework.data.mapping.PersonWithId");
520-
* Field field = class_2.getDeclaredField("id");
527+
* Field field = org.springframework.data.mapping.PersonWithId.class.getDeclaredField("id");
521528
* field.setAccessible(true);
522529
* $id_fieldGetter = lookup.unreflectGetter(field);
523530
* $id_fieldSetter = lookup.unreflectSetter(field);
@@ -539,37 +546,27 @@ private static void visitStaticInitializer(PersistentEntity<?, ?> entity,
539546
String.format("()%s", referenceName(JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP)), false);
540547
mv.visitVarInsn(ASTORE, 0);
541548

542-
List<Class<?>> entityClasses = getPropertyDeclaratingClasses(persistentProperties);
543-
544-
for (Class<?> entityClass : entityClasses) {
545-
546-
mv.visitLdcInsn(entityClass.getName());
547-
mv.visitMethodInsn(INVOKESTATIC, JAVA_LANG_CLASS, "forName",
548-
String.format("(%s)%s", referenceName(JAVA_LANG_STRING), referenceName(JAVA_LANG_CLASS)), false);
549-
mv.visitVarInsn(ASTORE, classVariableIndex5(entityClasses, entityClass));
550-
}
551-
552549
for (PersistentProperty<?> property : persistentProperties) {
553550

554551
if (property.usePropertyAccess()) {
555552

556553
if (generateMethodHandle(entity, property.getGetter())) {
557-
visitPropertyGetterInitializer(property, mv, entityClasses, internalClassName);
554+
visitPropertyGetterInitializer(property, mv, internalClassName);
558555
}
559556

560557
if (generateMethodHandle(entity, property.getSetter())) {
561-
visitPropertySetterInitializer(property.getSetter(), property, mv, entityClasses, internalClassName,
558+
visitPropertySetterInitializer(property.getSetter(), property, mv, internalClassName,
562559
PropertyAccessorClassGenerator::setterName, 2);
563560
}
564561
}
565562

566563
if (property.isImmutable() && generateMethodHandle(entity, property.getWither())) {
567-
visitPropertySetterInitializer(property.getWither(), property, mv, entityClasses, internalClassName,
564+
visitPropertySetterInitializer(property.getWither(), property, mv, internalClassName,
568565
PropertyAccessorClassGenerator::witherName, 4);
569566
}
570567

571568
if (generateSetterMethodHandle(entity, property.getField())) {
572-
visitFieldGetterSetterInitializer(property, mv, entityClasses, internalClassName);
569+
visitFieldGetterSetterInitializer(property, mv, internalClassName);
573570
}
574571
}
575572

@@ -582,14 +579,36 @@ private static void visitStaticInitializer(PersistentEntity<?, ?> entity,
582579
mv.visitLocalVariable("getter", referenceName(JAVA_LANG_REFLECT_METHOD), null, l0, l1, 3);
583580
mv.visitLocalVariable("wither", referenceName(JAVA_LANG_REFLECT_METHOD), null, l0, l1, 4);
584581

585-
for (Class<?> entityClass : entityClasses) {
582+
mv.visitMaxs(0, 0);
583+
mv.visitEnd();
584+
}
585+
586+
static boolean requiresMethodHandleSetup(PersistentEntity<?, ?> entity,
587+
List<PersistentProperty<?>> persistentProperties) {
588+
589+
for (PersistentProperty<?> property : persistentProperties) {
590+
591+
if (property.usePropertyAccess()) {
592+
593+
if (generateMethodHandle(entity, property.getGetter())) {
594+
return true;
595+
}
596+
597+
if (generateMethodHandle(entity, property.getSetter())) {
598+
return true;
599+
}
600+
}
601+
602+
if (property.isImmutable() && generateMethodHandle(entity, property.getWither())) {
603+
return true;
604+
}
586605

587-
int index = classVariableIndex5(entityClasses, entityClass);
588-
mv.visitLocalVariable(String.format("class_%d", index), referenceName(JAVA_LANG_CLASS), null, l0, l1, index);
606+
if (generateSetterMethodHandle(entity, property.getField())) {
607+
return true;
608+
}
589609
}
590610

591-
mv.visitMaxs(0, 0);
592-
mv.visitEnd();
611+
return false;
593612
}
594613

595614
/**
@@ -617,14 +636,14 @@ private static List<Class<?>> getPropertyDeclaratingClasses(List<PersistentPrope
617636
* Generate property getter initializer.
618637
*/
619638
private static void visitPropertyGetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
620-
List<Class<?>> entityClasses, String internalClassName) {
639+
String internalClassName) {
621640

622641
// getter = <entity>.class.getDeclaredMethod()
623642
Method getter = property.getGetter();
624643

625644
if (getter != null) {
626645

627-
mv.visitVarInsn(ALOAD, classVariableIndex5(entityClasses, getter.getDeclaringClass()));
646+
mv.visitLdcInsn(Type.getObjectType(Type.getInternalName(getter.getDeclaringClass())));
628647
mv.visitLdcInsn(getter.getName());
629648
mv.visitInsn(ICONST_0);
630649
mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_CLASS);
@@ -657,14 +676,14 @@ private static void visitPropertyGetterInitializer(PersistentProperty<?> propert
657676
* Generate property setter/wither initializer.
658677
*/
659678
private static void visitPropertySetterInitializer(@Nullable Method method, PersistentProperty<?> property,
660-
MethodVisitor mv, List<Class<?>> entityClasses, String internalClassName,
679+
MethodVisitor mv, String internalClassName,
661680
Function<PersistentProperty<?>, String> setterNameFunction, int localVariableIndex) {
662681

663682
// method = <entity>.class.getDeclaredMethod()
664683

665684
if (method != null) {
666685

667-
mv.visitVarInsn(ALOAD, classVariableIndex5(entityClasses, method.getDeclaringClass()));
686+
mv.visitLdcInsn(Type.getObjectType(Type.getInternalName(method.getDeclaringClass())));
668687
mv.visitLdcInsn(method.getName());
669688

670689
mv.visitInsn(ICONST_1);
@@ -711,14 +730,14 @@ private static void visitPropertySetterInitializer(@Nullable Method method, Pers
711730
* Generate field getter and setter initializers.
712731
*/
713732
private static void visitFieldGetterSetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
714-
List<Class<?>> entityClasses, String internalClassName) {
733+
String internalClassName) {
715734

716735
// field = <entity>.class.getDeclaredField()
717736

718737
Field field = property.getField();
719738
if (field != null) {
720739

721-
mv.visitVarInsn(ALOAD, classVariableIndex5(entityClasses, field.getDeclaringClass()));
740+
mv.visitLdcInsn(Type.getObjectType(Type.getInternalName(field.getDeclaringClass())));
722741
mv.visitLdcInsn(field.getName());
723742
mv.visitMethodInsn(INVOKEVIRTUAL, JAVA_LANG_CLASS, "getDeclaredField",
724743
String.format("(%s)%s", referenceName(JAVA_LANG_STRING), referenceName(JAVA_LANG_REFLECT_FIELD)), false);

0 commit comments

Comments
 (0)