DATACMNS-809 - Polishing.

Made as many methods in ClassGeneratingPropertyAccessorFactory static as possible. Some code formatting. Some warning suppressions where needed.

Original pull request: #159.
This commit is contained in:
Oliver Gierke
2016-04-30 13:18:12 +02:00
parent 899a98c83e
commit 41fe89743b
8 changed files with 167 additions and 147 deletions

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.mapping.model;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
@@ -63,12 +66,11 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
private final Map<String, P> propertyCache;
private final Map<Class<? extends Annotation>, Annotation> annotationCache;
private final PersistentPropertyAccessorFactory propertyAccessorFactory;
private P idProperty;
private P versionProperty;
private final PersistentPropertyAccessorFactory propertyAccessorFactory;
/**
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
*
@@ -440,17 +442,17 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
*
* @author Oliver Gierke
*/
@RequiredArgsConstructor
private static final class AssociationComparator<P extends PersistentProperty<P>>
implements Comparator<Association<P>>, Serializable {
private static final long serialVersionUID = 4508054194886854513L;
private final Comparator<P> delegate;
public AssociationComparator(Comparator<P> delegate) {
Assert.notNull(delegate);
this.delegate = delegate;
}
private final @NonNull Comparator<P> delegate;
/*
* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Association<P> left, Association<P> right) {
return delegate.compare(left.getInverse(), right.getInverse());
}

View File

@@ -13,11 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping.model;
import static org.springframework.asm.Opcodes.*;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.UtilityClass;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@@ -52,24 +55,17 @@ import org.springframework.util.ReflectionUtils;
* to overcome Java visibility issues or directly using field access/getter/setter calls.
*
* @author Mark Paluch
* @author Oliver Gierke
* @since 1.13
*/
class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
private static final boolean IS_JAVA_JAVA_7 = org.springframework.util.ClassUtils
private static final boolean IS_JAVA_7_OR_BETTER = org.springframework.util.ClassUtils
.isPresent("java.lang.invoke.MethodHandle", ClassGeneratingPropertyAccessorFactory.class.getClassLoader());
private final PropertyAccessorClassGenerator generator;
private volatile Map<TypeInformation<?>, Class<PersistentPropertyAccessor>> propertyAccessorClasses = new HashMap<TypeInformation<?>, Class<PersistentPropertyAccessor>>(
32);
/**
* Creates a new {@link ClassGeneratingPropertyAccessorFactory}.
*/
public ClassGeneratingPropertyAccessorFactory() {
this.generator = new PropertyAccessorClassGenerator();
}
/* (non-Javadoc)
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
*/
@@ -93,12 +89,12 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* Checks whether an accessor class can be generated.
*
* @param entity
* @return true if the runtime is equal or greater to Java 1.7, property name hash codes are unique and the type has a
* class loader we can use to re-inject types.
* @return {@literal true} if the runtime is equal or greater to Java 1.7, property name hash codes are unique and the
* type has a class loader we can use to re-inject types.
*/
public static boolean canGenerateAccessorClass(PersistentEntity<?, ?> entity) {
if (!IS_JAVA_JAVA_7) {
if (!IS_JAVA_7_OR_BETTER) {
return false;
}
@@ -108,18 +104,24 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
final Set<Integer> hashCodes = new HashSet<Integer>();
final AtomicInteger propertyCount = new AtomicInteger();
entity.doWithProperties(new SimplePropertyHandler() {
@Override
public void doWithPersistentProperty(PersistentProperty<?> property) {
hashCodes.add(property.getName().hashCode());
propertyCount.incrementAndGet();
}
});
entity.doWithAssociations(new SimpleAssociationHandler() {
@Override
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
if (association.getInverse() != null) {
hashCodes.add(association.getInverse().getName().hashCode());
propertyCount.incrementAndGet();
}
@@ -130,7 +132,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
}
/**
* @param entity
* @param entity must not be {@literal null}.
* @return
*/
private synchronized Class<PersistentPropertyAccessor> potentiallyCreateAndRegisterPersistentPropertyAccessorClass(
@@ -157,7 +159,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
private Class<PersistentPropertyAccessor> createAccessorClass(PersistentEntity<?, ?> entity) {
try {
return (Class<PersistentPropertyAccessor>) this.generator.generateCustomAccessorClass(entity);
return (Class<PersistentPropertyAccessor>) PropertyAccessorClassGenerator.generateCustomAccessorClass(entity);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -260,28 +262,18 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
private static final String[] IMPLEMENTED_INTERFACES = new String[] {
Type.getInternalName(PersistentPropertyAccessor.class) };
public PropertyAccessorClassGenerator() {}
/**
* @param entity
* @return
*/
private String generateClassName(PersistentEntity<?, ?> entity) {
return entity.getType().getName() + TAG + Integer.toString(entity.hashCode(), 36);
}
/**
* Generate a new class for the given {@link PersistentEntity}.
*
* @param entity
* @return
*/
public Class<?> generateCustomAccessorClass(PersistentEntity<?, ?> entity) {
public static Class<?> generateCustomAccessorClass(PersistentEntity<?, ?> entity) {
String className = generateClassName(entity);
byte[] bytecode = generateBytecode(className.replace('.', '/'), entity);
Class<?> accessorClass = Evil.injector.defineClass(className, bytecode, 0, bytecode.length, entity);
Class<?> accessorClass = Evil.defineClass(className, bytecode, 0, bytecode.length, entity);
return accessorClass;
}
@@ -293,7 +285,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param entity
* @return
*/
public byte[] generateBytecode(String internalClassName, PersistentEntity<?, ?> entity) {
public static byte[] generateBytecode(String internalClassName, PersistentEntity<?, ?> entity) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(Opcodes.V1_6, ACC_PUBLIC + ACC_SUPER, internalClassName, null, JAVA_LANG_OBJECT, IMPLEMENTED_INTERFACES);
@@ -312,10 +304,12 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
return cw.toByteArray();
}
private List<PersistentProperty<?>> getPersistentProperties(PersistentEntity<?, ?> entity) {
private static List<PersistentProperty<?>> getPersistentProperties(PersistentEntity<?, ?> entity) {
final List<PersistentProperty<?>> persistentProperties = new ArrayList<PersistentProperty<?>>();
entity.doWithAssociations(new SimpleAssociationHandler() {
@Override
public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {
if (association.getInverse() != null) {
@@ -325,11 +319,13 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
});
entity.doWithProperties(new SimplePropertyHandler() {
@Override
public void doWithPersistentProperty(PersistentProperty<?> property) {
persistentProperties.add(property);
}
});
return persistentProperties;
}
@@ -350,13 +346,14 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param persistentProperties
* @param cw
*/
private void visitFields(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
private static void visitFields(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
ClassWriter cw) {
cw.visitInnerClass(JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP, JAVA_LANG_INVOKE_METHOD_HANDLES, "Lookup",
ACC_PRIVATE + ACC_FINAL + ACC_STATIC);
boolean accessibleType = isAccessible(entity);
if (accessibleType) {
cw.visitField(ACC_PRIVATE + ACC_FINAL, BEAN_FIELD, referenceName(Type.getInternalName(entity.getType())), null,
null).visitEnd();
@@ -367,19 +364,24 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
for (PersistentProperty<?> property : persistentProperties) {
Method setter = property.getSetter();
if (setter != null && generateMethodHandle(entity, setter)) {
cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, setterName(property),
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd();
}
Method getter = property.getGetter();
if (getter != null && generateMethodHandle(entity, getter)) {
cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, getterName(property),
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd();
}
Field field = property.getField();
if (field != null && generateSetterMethodHandle(entity, field)) {
cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, fieldSetterName(property),
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE), null, null).visitEnd();
cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, fieldGetterName(property),
@@ -404,11 +406,13 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param cw
*/
private void visitDefaultConstructor(PersistentEntity<?, ?> entity, String internalClassName, ClassWriter cw) {
private static void visitDefaultConstructor(PersistentEntity<?, ?> entity, String internalClassName,
ClassWriter cw) {
// public EntityAccessor(Entity bean) or EntityAccessor(Object bean)
MethodVisitor mv;
boolean accessibleType = isAccessible(entity);
if (accessibleType) {
mv = cw.visitMethod(ACC_PUBLIC, INIT, String.format("(%s)V", referenceName(entity.getType())), null, null);
} else {
@@ -475,8 +479,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param cw
*/
private void visitStaticInitializer(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
String internalClassName, ClassWriter cw) {
private static void visitStaticInitializer(PersistentEntity<?, ?> entity,
List<PersistentProperty<?>> persistentProperties, String internalClassName, ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_STATIC, CLINIT, "()V", null, null);
mv.visitCode();
@@ -492,6 +496,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
List<Class<?>> entityClasses = getPropertyDeclaratingClasses(persistentProperties);
for (Class<?> entityClass : entityClasses) {
mv.visitLdcInsn(entityClass.getName());
mv.visitMethodInsn(INVOKESTATIC, JAVA_LANG_CLASS, "forName",
String.format("(%s)%s", referenceName(JAVA_LANG_STRING), referenceName(JAVA_LANG_CLASS)), false);
@@ -522,8 +527,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
mv.visitLocalVariable("getter", referenceName(JAVA_LANG_REFLECT_METHOD), null, l0, l1, 3);
for (Class<?> entityClass : entityClasses) {
int index = classVariableIndex4(entityClasses, entityClass);
int index = classVariableIndex4(entityClasses, entityClass);
mv.visitLocalVariable(String.format("class_%d", index), referenceName(JAVA_LANG_CLASS), null, l0, l1, index);
}
@@ -538,17 +543,20 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param persistentProperties
* @return
*/
private List<Class<?>> getPropertyDeclaratingClasses(List<PersistentProperty<?>> persistentProperties) {
private static List<Class<?>> getPropertyDeclaratingClasses(List<PersistentProperty<?>> persistentProperties) {
Set<Class<?>> entityClassesSet = new HashSet<Class<?>>();
for (PersistentProperty<?> property : persistentProperties) {
if (property.getField() != null) {
entityClassesSet.add(property.getField().getDeclaringClass());
}
if (property.getGetter() != null) {
entityClassesSet.add(property.getGetter().getDeclaringClass());
}
if (property.getSetter() != null) {
entityClassesSet.add(property.getSetter().getDeclaringClass());
}
@@ -565,11 +573,12 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param entityClasses
* @param internalClassName
*/
private void visitPropertyGetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
private static void visitPropertyGetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
List<Class<?>> entityClasses, String internalClassName) {
// getter = <entity>.class.getDeclaredMethod()
Method getter = property.getGetter();
if (getter != null) {
mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, getter.getDeclaringClass()));
mv.visitLdcInsn(getter.getName());
@@ -593,6 +602,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
} else {
mv.visitInsn(ACONST_NULL);
}
mv.visitFieldInsn(PUTSTATIC, internalClassName, getterName(property),
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE));
}
@@ -605,11 +615,12 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param entityClasses
* @param internalClassName
*/
private void visitPropertySetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
private static void visitPropertySetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
List<Class<?>> entityClasses, String internalClassName) {
// setter = <entity>.class.getDeclaredMethod()
Method setter = property.getSetter();
if (setter != null) {
mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, setter.getDeclaringClass()));
@@ -652,8 +663,9 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param entityClasses
* @param internalClassName
*/
private void visitFieldGetterSetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
private static void visitFieldGetterSetterInitializer(PersistentProperty<?> property, MethodVisitor mv,
List<Class<?>> entityClasses, String internalClassName) {
// field = <entity>.class.getDeclaredField()
Field field = property.getField();
mv.visitVarInsn(ALOAD, classVariableIndex4(entityClasses, field.getDeclaringClass()));
@@ -684,7 +696,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
referenceName(JAVA_LANG_INVOKE_METHOD_HANDLE));
}
private void visitBeanGetter(PersistentEntity<?, ?> entity, String internalClassName, ClassWriter cw) {
private static void visitBeanGetter(PersistentEntity<?, ?> entity, String internalClassName, ClassWriter cw) {
// public Object getBean()
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getBean", String.format("()%s", referenceName(JAVA_LANG_OBJECT)),
@@ -695,11 +707,13 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
// return this.bean
mv.visitLabel(l0);
mv.visitVarInsn(ALOAD, 0);
if (isAccessible(entity)) {
mv.visitFieldInsn(GETFIELD, internalClassName, BEAN_FIELD, referenceName(entity.getType()));
} else {
mv.visitFieldInsn(GETFIELD, internalClassName, BEAN_FIELD, referenceName(JAVA_LANG_OBJECT));
}
mv.visitInsn(ARETURN);
Label l1 = new Label();
@@ -738,8 +752,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param cw
*/
private void visitGetProperty(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
String internalClassName, ClassWriter cw) {
private static void visitGetProperty(PersistentEntity<?, ?> entity,
List<PersistentProperty<?>> persistentProperties, String internalClassName, ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getProperty",
"(Lorg/springframework/data/mapping/PersistentProperty;)Ljava/lang/Object;",
@@ -754,6 +768,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
visitAssertNotNull(mv);
mv.visitVarInsn(ALOAD, 0);
if (isAccessible(entity)) {
mv.visitFieldInsn(GETFIELD, internalClassName, BEAN_FIELD, referenceName(entity.getType()));
} else {
@@ -788,8 +803,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param mv
*/
private void visitGetPropertySwitch(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
String internalClassName, MethodVisitor mv) {
private static void visitGetPropertySwitch(PersistentEntity<?, ?> entity,
List<PersistentProperty<?>> persistentProperties, String internalClassName, MethodVisitor mv) {
Map<String, PropertyStackAddress> propertyStackMap = createPropertyStackMap(persistentProperties);
@@ -799,6 +814,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
Collections.sort(stackmap);
for (int i = 0; i < stackmap.size(); i++) {
PropertyStackAddress propertyStackAddress = stackmap.get(i);
hashes[i] = propertyStackAddress.hash;
switchJumpLabels[i] = propertyStackAddress.label;
@@ -838,8 +854,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param mv
* @param internalClassName
*/
private void visitGetProperty0(PersistentEntity<?, ?> entity, PersistentProperty<?> property, MethodVisitor mv,
String internalClassName) {
private static void visitGetProperty0(PersistentEntity<?, ?> entity, PersistentProperty<?> property,
MethodVisitor mv, String internalClassName) {
Method getter = property.getGetter();
if (property.usePropertyAccess() && getter != null) {
@@ -905,8 +921,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param cw
*/
private void visitSetProperty(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
String internalClassName, ClassWriter cw) {
private static void visitSetProperty(PersistentEntity<?, ?> entity,
List<PersistentProperty<?>> persistentProperties, String internalClassName, ClassWriter cw) {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "setProperty",
"(Lorg/springframework/data/mapping/PersistentProperty;Ljava/lang/Object;)V",
@@ -919,6 +935,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
visitAssertNotNull(mv);
mv.visitVarInsn(ALOAD, 0);
if (isAccessible(entity)) {
mv.visitFieldInsn(GETFIELD, internalClassName, BEAN_FIELD, referenceName(entity.getType()));
} else {
@@ -957,8 +974,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param internalClassName
* @param mv
*/
private void visitSetPropertySwitch(PersistentEntity<?, ?> entity, List<PersistentProperty<?>> persistentProperties,
String internalClassName, MethodVisitor mv) {
private static void visitSetPropertySwitch(PersistentEntity<?, ?> entity,
List<PersistentProperty<?>> persistentProperties, String internalClassName, MethodVisitor mv) {
Map<String, PropertyStackAddress> propertyStackMap = createPropertyStackMap(persistentProperties);
@@ -1006,8 +1023,8 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param mv
* @param internalClassName
*/
private void visitSetProperty0(PersistentEntity<?, ?> entity, PersistentProperty<?> property, MethodVisitor mv,
String internalClassName) {
private static void visitSetProperty0(PersistentEntity<?, ?> entity, PersistentProperty<?> property,
MethodVisitor mv, String internalClassName) {
Method setter = property.getSetter();
if (property.usePropertyAccess() && setter != null) {
@@ -1061,7 +1078,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
mv.visitInsn(RETURN);
}
private void visitAssertNotNull(MethodVisitor mv) {
private static void visitAssertNotNull(MethodVisitor mv) {
// Assert.notNull(property)
mv.visitVarInsn(ALOAD, 1);
@@ -1070,7 +1087,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
String.format("(%s%s)V", referenceName(JAVA_LANG_OBJECT), referenceName(JAVA_LANG_STRING)), false);
}
private void visitThrowUnsupportedOperationException(MethodVisitor mv, String message) {
private static void visitThrowUnsupportedOperationException(MethodVisitor mv, String message) {
// throw new UnsupportedOperationException(msg)
mv.visitTypeInsn(NEW, JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION);
@@ -1089,40 +1106,35 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
mv.visitInsn(ATHROW);
}
private String fieldSetterName(PersistentProperty<?> property) {
private static String fieldSetterName(PersistentProperty<?> property) {
return String.format("$%s_fieldSetter", property.getName());
}
private String fieldGetterName(PersistentProperty<?> property) {
private static String fieldGetterName(PersistentProperty<?> property) {
return String.format("$%s_fieldGetter", property.getName());
}
private String setterName(PersistentProperty<?> property) {
private static String setterName(PersistentProperty<?> property) {
return String.format("$%s_setter", property.getName());
}
private String getterName(PersistentProperty<?> property) {
private static String getterName(PersistentProperty<?> property) {
return String.format("$%s_getter", property.getName());
}
private boolean isAccessible(PersistentEntity<?, ?> entity) {
private static boolean isAccessible(PersistentEntity<?, ?> entity) {
return isAccessible(entity.getType());
}
private boolean isAccessible(Class<?> theClass) {
private static boolean isAccessible(Class<?> theClass) {
return isAccessible(theClass.getModifiers());
}
private boolean isAccessible(int modifiers) {
if (Modifier.isPrivate(modifiers)) {
return false;
}
return true;
private static boolean isAccessible(int modifiers) {
return !Modifier.isPrivate(modifiers);
}
private boolean isDefault(int modifiers) {
private static boolean isDefault(int modifiers) {
if (Modifier.isPrivate(modifiers) || Modifier.isProtected(modifiers) || Modifier.isPublic(modifiers)) {
return false;
@@ -1131,7 +1143,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
return true;
}
private boolean generateSetterMethodHandle(PersistentEntity<?, ?> entity, Field field) {
private static boolean generateSetterMethodHandle(PersistentEntity<?, ?> entity, Field field) {
return generateMethodHandle(entity, field) || Modifier.isFinal(field.getModifiers());
}
@@ -1144,7 +1156,7 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param member
* @return
*/
private boolean generateMethodHandle(PersistentEntity<?, ?> entity, Member member) {
private static boolean generateMethodHandle(PersistentEntity<?, ?> entity, Member member) {
if (isAccessible(entity)) {
@@ -1168,10 +1180,17 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param item
* @return
*/
private int classVariableIndex4(List<Class<?>> list, Class<?> item) {
private static int classVariableIndex4(List<Class<?>> list, Class<?> item) {
return 4 + list.indexOf(item);
}
/**
* @param entity
* @return
*/
private static String generateClassName(PersistentEntity<?, ?> entity) {
return entity.getType().getName() + TAG + Integer.toString(entity.hashCode(), 36);
}
}
private static String referenceName(Class<?> type) {
@@ -1244,83 +1263,83 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
}
/**
* Autobox/Auto-unbox primitives to object and vice versa.
* Auto-box/Auto-unbox primitives to object and vice versa.
*
* @param in the input type
* @param out the expected output type
* @param mv
* @param visitor
*/
private static void autoboxIfNeeded(Class<?> in, Class<?> out, MethodVisitor mv) {
private static void autoboxIfNeeded(Class<?> in, Class<?> out, MethodVisitor visitor) {
if (in.equals(Boolean.class) && out.equals(Boolean.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
}
if (in.equals(Boolean.TYPE) && out.equals(Boolean.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
}
if (in.equals(Byte.class) && out.equals(Byte.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
}
if (in.equals(Byte.TYPE) && out.equals(Byte.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
}
if (in.equals(Character.class) && out.equals(Character.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
}
if (in.equals(Character.TYPE) && out.equals(Character.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
}
if (in.equals(Double.class) && out.equals(Double.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
}
if (in.equals(Double.TYPE) && out.equals(Double.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
}
if (in.equals(Float.class) && out.equals(Float.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
}
if (in.equals(Float.TYPE) && out.equals(Float.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
}
if (in.equals(Integer.class) && out.equals(Integer.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
}
if (in.equals(Integer.TYPE) && out.equals(Integer.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
}
if (in.equals(Long.class) && out.equals(Long.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
}
if (in.equals(Long.TYPE) && out.equals(Long.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
}
if (in.equals(Short.class) && out.equals(Short.TYPE)) {
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
visitor.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
}
if (in.equals(Short.TYPE) && out.equals(Short.class)) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
visitor.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
}
}
/**
* Returns the signature type for a {@link Class} including primitives.
*
* @param type
* @param type must not be {@literal null}.
* @return
*/
private static String signatureTypeName(Class<?> type) {
@@ -1369,16 +1388,16 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
*
* @author Mark Paluch
*/
@RequiredArgsConstructor
static class PropertyStackAddress implements Comparable<PropertyStackAddress> {
final int hash;
final Label label;
public PropertyStackAddress(Label label, int hash) {
this.label = label;
this.hash = hash;
}
private final @NonNull Label label;
private final int hash;
/*
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(PropertyStackAddress o) {
return (hash < o.hash) ? -1 : ((hash == o.hash) ? 0 : 1);
@@ -1392,12 +1411,9 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
*
* @author Mark Paluch
*/
@UtilityClass
private static class Evil {
final static Evil injector = new Evil();
private Evil() {}
/**
* Define a Class in the {@link ClassLoader} of the {@link PersistentEntity} type.
*
@@ -1408,10 +1424,12 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
* @param persistentEntity
* @return
*/
@SuppressWarnings("rawtypes")
Class<?> defineClass(String name, byte[] bytes, int offset, int len, PersistentEntity<?, ?> persistentEntity) {
ClassLoader classLoader = persistentEntity.getType().getClassLoader();
Class<?> classLoaderClass = classLoader.getClass();
try {
Class<? extends PersistentEntity> persistentEntityClass = persistentEntity.getClass();
@@ -1421,10 +1439,10 @@ class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccess
return (Class<?>) defineClass.invoke(classLoader, name, bytes, offset, len,
persistentEntityClass.getProtectionDomain());
} catch (ReflectiveOperationException e) {
throw new IllegalStateException(e);
}
}
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping.model;
import org.springframework.data.mapping.PersistentEntity;
@@ -24,22 +23,21 @@ import org.springframework.data.mapping.PersistentPropertyAccessor;
* reflection or use generated classes with direct field/method access.
*
* @author Mark Paluch
* @author Oliver Gierke
* @since 1.13
*/
public class DefaultPersistentPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
private final ClassGeneratingPropertyAccessorFactory classGeneratingPropertyAccessorFactory = new ClassGeneratingPropertyAccessorFactory();
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.PersistentPropertyAccessorFactory#getPropertyAccessor(org.springframework.data.mapping.PersistentEntity, java.lang.Object)
*/
@Override
public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean) {
if (ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)) {
return classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean);
}
return new BeanWrapper<Object>(bean);
return ClassGeneratingPropertyAccessorFactory.canGenerateAccessorClass(entity)
? classGeneratingPropertyAccessorFactory.getPropertyAccessor(entity, bean) : new BeanWrapper<Object>(bean);
}
}

View File

@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mapping.model;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentPropertyAccessor;
/**
* Factory to create {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}.
* Factory to create {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and bean instance.
*
* @author Mark Paluch
* @author Oliver Gierke
* @since 1.13
*/
public interface PersistentPropertyAccessorFactory {
@@ -30,9 +30,9 @@ public interface PersistentPropertyAccessorFactory {
/**
* Returns a {@link PersistentPropertyAccessor} for a given {@link PersistentEntity} and {@code bean}.
*
* @param bean
* @return
* @param entity must not be {@literal null}.
* @param bean must not be {@literal null}.
* @return will never be {@literal null}.
*/
PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> entity, Object bean);
}