Check BeanInfoFactory for interface introspection as well

Issue: SPR-16322
This commit is contained in:
Juergen Hoeller
2018-01-08 18:05:02 +01:00
parent 446e7ed25c
commit 45828cb934
3 changed files with 59 additions and 50 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,16 +16,10 @@
package org.springframework.core;
import java.io.Externalizable;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -47,19 +41,7 @@ public abstract class Conventions {
*/
private static final String PLURAL_SUFFIX = "List";
/**
* Set of interfaces that are supposed to be ignored
* when searching for the 'primary' interface of a proxy.
*/
private static final Set<Class<?>> IGNORED_INTERFACES;
static {
IGNORED_INTERFACES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
Serializable.class, Externalizable.class, Cloneable.class, Comparable.class)));
}
private static final ReactiveAdapterRegistry reactiveAdapterRegistry =
ReactiveAdapterRegistry.getSharedInstance();
private static final ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
@@ -67,16 +49,13 @@ public abstract class Conventions {
* based on its concrete type. The convention used is to return the
* un-capitalized short name of the {@code Class}, according to JavaBeans
* property naming rules.
*
* <p>For example:<br>
* {@code com.myapp.Product} becomes {@code "product"}<br>
* {@code com.myapp.MyProduct} becomes {@code "myProduct"}<br>
* {@code com.myapp.UKProduct} becomes {@code "UKProduct"}<br>
*
* <p>For arrays the pluralized version of the array component type is used.
* For {@code Collection}s an attempt is made to 'peek ahead' to determine
* the component type and return its pluralized version.
*
* @param value the value to generate a variable name for
* @return the generated variable name
*/
@@ -110,12 +89,10 @@ public abstract class Conventions {
/**
* Determine the conventional variable name for the given parameter taking
* the generic collection type, if any, into account.
*
* <p>As of 5.0 this method supports reactive types:<br>
* {@code Mono<com.myapp.Product>} becomes {@code "productMono"}<br>
* {@code Flux<com.myapp.MyProduct>} becomes {@code "myProductFlux"}<br>
* {@code Observable<com.myapp.MyProduct>} becomes {@code "myProductObservable"}<br>
*
* @param parameter the method or constructor parameter
* @return the generated variable name
*/
@@ -295,7 +272,7 @@ public abstract class Conventions {
if (Proxy.isProxyClass(valueClass)) {
Class<?>[] ifcs = valueClass.getInterfaces();
for (Class<?> ifc : ifcs) {
if (!IGNORED_INTERFACES.contains(ifc)) {
if (!ClassUtils.isJavaLanguageInterface(ifc)) {
return ifc;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,8 @@
package org.springframework.util;
import java.beans.Introspector;
import java.io.Externalizable;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@@ -74,6 +76,13 @@ public abstract class ClassUtils {
public static final String CLASS_FILE_SUFFIX = ".class";
/**
* Common Java language interfaces which are supposed to be ignored
* when searching for 'primary' user-level interfaces.
*/
private static final Set<Class<?>> javaLanguageInterfaces = new HashSet<>(
Arrays.asList(Serializable.class, Externalizable.class, Cloneable.class, Comparable.class));
/**
* Map with primitive wrapper type as key and corresponding primitive
* type as value, for example: Integer.class -> int.class.
@@ -1218,6 +1227,19 @@ public abstract class ClassUtils {
}
}
/**
* Determine whether the given interface is a common Java language interface:
* {@link Serializable}, {@link Externalizable}, {@link Cloneable}, {@link Comparable}
* - all of which can be ignored when looking for 'primary' user-level interfaces.
* Common characteristics: no service-level operations, no bean property methods,
* no default methods.
* @param ifc the interface to check
* @since 5.0.3
*/
public static boolean isJavaLanguageInterface(Class<?> ifc) {
return javaLanguageInterfaces.contains(ifc);
}
/**
* Check whether the given object is a CGLIB proxy.
* @param object the object to check