Perform basic property determination without java.beans.Introspector

Closes gh-29320
This commit is contained in:
Juergen Hoeller
2022-10-13 19:02:45 +02:00
parent 113db2fb2f
commit bba313c2f5
12 changed files with 276 additions and 199 deletions

View File

@@ -16,10 +16,6 @@
package org.springframework.aot.hint;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.RecordComponent;
import java.lang.reflect.Type;
@@ -92,17 +88,14 @@ public class BindingReflectionHintsRegistrar {
typeHint.withMembers(
MemberCategory.DECLARED_FIELDS,
MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
try {
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
registerPropertyHints(hints, seen, propertyDescriptor.getWriteMethod(), 0);
registerPropertyHints(hints, seen, propertyDescriptor.getReadMethod(), -1);
for (Method method : clazz.getMethods()) {
String methodName = method.getName();
if (methodName.startsWith("set") && method.getParameterCount() == 1) {
registerPropertyHints(hints, seen, method, 0);
}
}
catch (IntrospectionException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring referenced type [" + clazz.getName() + "]: " + ex.getMessage());
else if ((methodName.startsWith("get") && method.getParameterCount() == 0 && method.getReturnType() != Void.TYPE) ||
(methodName.startsWith("is") && method.getParameterCount() == 0 && method.getReturnType() == boolean.class)) {
registerPropertyHints(hints, seen, method, -1);
}
}
}
@@ -125,8 +118,8 @@ public class BindingReflectionHintsRegistrar {
}
private void registerPropertyHints(ReflectionHints hints, Set<Type> seen, @Nullable Method method, int parameterIndex) {
if (method != null && method.getDeclaringClass() != Object.class
&& method.getDeclaringClass() != Enum.class) {
if (method != null && method.getDeclaringClass() != Object.class &&
method.getDeclaringClass() != Enum.class) {
hints.registerMethod(method, ExecutableMode.INVOKE);
MethodParameter methodParameter = MethodParameter.forExecutable(method, parameterIndex);
Type methodParameterType = methodParameter.getGenericParameterType();

View File

@@ -16,7 +16,6 @@
package org.springframework.util;
import java.beans.Introspector;
import java.io.Closeable;
import java.io.Externalizable;
import java.io.Serializable;
@@ -997,13 +996,13 @@ public abstract class ClassUtils {
* property format. Strips the outer class name in case of a nested class.
* @param clazz the class
* @return the short name rendered in a standard JavaBeans property format
* @see java.beans.Introspector#decapitalize(String)
* @see StringUtils#uncapitalizeAsProperty(String)
*/
public static String getShortNameAsProperty(Class<?> clazz) {
String shortName = getShortName(clazz);
int dotIndex = shortName.lastIndexOf(PACKAGE_SEPARATOR);
shortName = (dotIndex != -1 ? shortName.substring(dotIndex + 1) : shortName);
return Introspector.decapitalize(shortName);
return StringUtils.uncapitalizeAsProperty(shortName);
}
/**

View File

@@ -554,6 +554,24 @@ public abstract class StringUtils {
return changeFirstCharacterCase(str, false);
}
/**
* Uncapitalize a {@code String} in JavaBeans property format,
* changing the first letter to lower case as per
* {@link Character#toLowerCase(char)}, unless the initial two
* letters are upper case in direct succession.
* @param str the {@code String} to uncapitalize
* @return the uncapitalized {@code String}
* @since 6.0
* @see java.beans.Introspector#decapitalize(String)
*/
public static String uncapitalizeAsProperty(String str) {
if (!hasLength(str) || (str.length() > 1 && Character.isUpperCase(str.charAt(0)) &&
Character.isUpperCase(str.charAt(1)))) {
return str;
}
return changeFirstCharacterCase(str, false);
}
private static String changeFirstCharacterCase(String str, boolean capitalize) {
if (!hasLength(str)) {
return str;