CachedIntrospectionResults.java (spring-framework-5.3.23) | : | CachedIntrospectionResults.java (spring-framework-5.3.24) | ||
---|---|---|---|---|
skipping to change at line 100 | skipping to change at line 100 | |||
* <p>Note that such an effect may also indicate a scenario where caching doesn't work | * <p>Note that such an effect may also indicate a scenario where caching doesn't work | |||
* effectively: Prefer an arrangement where the Spring jars live in the s ame ClassLoader | * effectively: Prefer an arrangement where the Spring jars live in the s ame ClassLoader | |||
* as the application classes, which allows for clean caching along with the application's | * as the application classes, which allows for clean caching along with the application's | |||
* lifecycle in any case. For a web application, consider declaring a loc al | * lifecycle in any case. For a web application, consider declaring a loc al | |||
* {@link org.springframework.web.util.IntrospectorCleanupListener} in {@ code web.xml} | * {@link org.springframework.web.util.IntrospectorCleanupListener} in {@ code web.xml} | |||
* in case of a multi-ClassLoader layout, which will allow for effective caching as well. | * in case of a multi-ClassLoader layout, which will allow for effective caching as well. | |||
* @see Introspector#getBeanInfo(Class, int) | * @see Introspector#getBeanInfo(Class, int) | |||
*/ | */ | |||
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beanin fo.ignore"; | public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beanin fo.ignore"; | |||
private static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY | ||||
= {}; | ||||
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses = | private static final boolean shouldIntrospectorIgnoreBeaninfoClasses = | |||
SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME); | SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME); | |||
/** Stores the BeanInfoFactory instances. */ | /** Stores the BeanInfoFactory instances. */ | |||
private static final List<BeanInfoFactory> beanInfoFactories = SpringFact oriesLoader.loadFactories( | private static final List<BeanInfoFactory> beanInfoFactories = SpringFact oriesLoader.loadFactories( | |||
BeanInfoFactory.class, CachedIntrospectionResults.class.g etClassLoader()); | BeanInfoFactory.class, CachedIntrospectionResults.class.g etClassLoader()); | |||
private static final Log logger = LogFactory.getLog(CachedIntrospectionRe sults.class); | private static final Log logger = LogFactory.getLog(CachedIntrospectionRe sults.class); | |||
/** | /** | |||
skipping to change at line 296 | skipping to change at line 294 | |||
for (PropertyDescriptor pd : pds) { | for (PropertyDescriptor pd : pds) { | |||
if (Class.class == beanClass && !("name".equals(p d.getName()) || | if (Class.class == beanClass && !("name".equals(p d.getName()) || | |||
(pd.getName().endsWith("Name") && String.class == pd.getPropertyType()))) { | (pd.getName().endsWith("Name") && String.class == pd.getPropertyType()))) { | |||
// Only allow all name variants of Class properties | // Only allow all name variants of Class properties | |||
continue; | continue; | |||
} | } | |||
if (URL.class == beanClass && "content".equals(pd .getName())) { | if (URL.class == beanClass && "content".equals(pd .getName())) { | |||
// Only allow URL attribute introspection , not content resolution | // Only allow URL attribute introspection , not content resolution | |||
continue; | continue; | |||
} | } | |||
if (pd.getWriteMethod() == null && isInvalidReadO nlyPropertyType(pd.getPropertyType())) { | if (pd.getWriteMethod() == null && isInvalidReadO nlyPropertyType(pd.getPropertyType(), beanClass)) { | |||
// Ignore read-only properties such as Cl assLoader - no need to bind to those | // Ignore read-only properties such as Cl assLoader - no need to bind to those | |||
continue; | continue; | |||
} | } | |||
if (logger.isTraceEnabled()) { | if (logger.isTraceEnabled()) { | |||
logger.trace("Found bean property '" + pd .getName() + "'" + | logger.trace("Found bean property '" + pd .getName() + "'" + | |||
(pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") + | (pd.getPropertyType() != null ? " of type [" + pd.getPropertyType().getName() + "]" : "") + | |||
(pd.getPropertyEditorClas s() != null ? | (pd.getPropertyEditorClas s() != null ? | |||
"; editor [" + pd.getPropertyEditorClass().getName() + "]" : "")); | "; editor [" + pd.getPropertyEditorClass().getName() + "]" : "")); | |||
} | } | |||
pd = buildGenericTypeAwarePropertyDescriptor(bean Class, pd); | pd = buildGenericTypeAwarePropertyDescriptor(bean Class, pd); | |||
skipping to change at line 346 | skipping to change at line 344 | |||
for (Class<?> ifc : currClass.getInterfaces()) { | for (Class<?> ifc : currClass.getInterfaces()) { | |||
if (!ClassUtils.isJavaLanguageInterface(ifc)) { | if (!ClassUtils.isJavaLanguageInterface(ifc)) { | |||
for (PropertyDescriptor pd : getBeanInfo(ifc).get PropertyDescriptors()) { | for (PropertyDescriptor pd : getBeanInfo(ifc).get PropertyDescriptors()) { | |||
PropertyDescriptor existingPd = this.prop ertyDescriptors.get(pd.getName()); | PropertyDescriptor existingPd = this.prop ertyDescriptors.get(pd.getName()); | |||
if (existingPd == null || | if (existingPd == null || | |||
(existingPd.getReadMethod () == null && pd.getReadMethod() != null)) { | (existingPd.getReadMethod () == null && pd.getReadMethod() != null)) { | |||
// GenericTypeAwarePropertyDescri ptor leniently resolves a set* write method | // GenericTypeAwarePropertyDescri ptor leniently resolves a set* write method | |||
// against a declared read method , so we prefer read method descriptors here. | // against a declared read method , so we prefer read method descriptors here. | |||
pd = buildGenericTypeAwarePropert yDescriptor(beanClass, pd); | pd = buildGenericTypeAwarePropert yDescriptor(beanClass, pd); | |||
if (pd.getWriteMethod() == null & | if (pd.getWriteMethod() == null & | |||
& isInvalidReadOnlyPropertyType(pd.getPropertyType())) { | & | |||
isInvalidReadOnly | ||||
PropertyType(pd.getPropertyType(), beanClass)) { | ||||
// Ignore read-only prope rties such as ClassLoader - no need to bind to those | // Ignore read-only prope rties such as ClassLoader - no need to bind to those | |||
continue; | continue; | |||
} | } | |||
this.propertyDescriptors.put(pd.g etName(), pd); | this.propertyDescriptors.put(pd.g etName(), pd); | |||
Method readMethod = pd.getReadMet hod(); | Method readMethod = pd.getReadMet hod(); | |||
if (readMethod != null) { | if (readMethod != null) { | |||
readMethodNames.add(readM ethod.getName()); | readMethodNames.add(readM ethod.getName()); | |||
} | } | |||
} | } | |||
} | } | |||
skipping to change at line 379 | skipping to change at line 378 | |||
new GenericTypeAwarePropertyDescr iptor(beanClass, method.getName(), method, null, null)); | new GenericTypeAwarePropertyDescr iptor(beanClass, method.getName(), method, null, null)); | |||
readMethodNames.add(method.getName()); | readMethodNames.add(method.getName()); | |||
} | } | |||
} | } | |||
} | } | |||
private boolean isPlainAccessor(Method method) { | private boolean isPlainAccessor(Method method) { | |||
if (Modifier.isStatic(method.getModifiers()) || | if (Modifier.isStatic(method.getModifiers()) || | |||
method.getDeclaringClass() == Object.class || met hod.getDeclaringClass() == Class.class || | method.getDeclaringClass() == Object.class || met hod.getDeclaringClass() == Class.class || | |||
method.getParameterCount() > 0 || method.getRetur nType() == void.class || | method.getParameterCount() > 0 || method.getRetur nType() == void.class || | |||
isInvalidReadOnlyPropertyType(method.getReturnTyp e())) { | isInvalidReadOnlyPropertyType(method.getReturnTyp e(), method.getDeclaringClass())) { | |||
return false; | return false; | |||
} | } | |||
try { | try { | |||
// Accessor method referring to instance field of same na me? | // Accessor method referring to instance field of same na me? | |||
method.getDeclaringClass().getDeclaredField(method.getNam e()); | method.getDeclaringClass().getDeclaredField(method.getNam e()); | |||
return true; | return true; | |||
} | } | |||
catch (Exception ex) { | catch (Exception ex) { | |||
return false; | return false; | |||
} | } | |||
} | } | |||
private boolean isInvalidReadOnlyPropertyType(@Nullable Class<?> returnTy | private boolean isInvalidReadOnlyPropertyType(@Nullable Class<?> returnTy | |||
pe) { | pe, Class<?> beanClass) { | |||
return (returnType != null && (AutoCloseable.class.isAssignableFr | return (returnType != null && (ClassLoader.class.isAssignableFrom | |||
om(returnType) || | (returnType) || | |||
ClassLoader.class.isAssignableFrom(returnType) || | ProtectionDomain.class.isAssignableFrom(returnTyp | |||
ProtectionDomain.class.isAssignableFrom(returnTyp | e) || | |||
e))); | (AutoCloseable.class.isAssignableFrom(returnType) | |||
&& | ||||
!AutoCloseable.class.isAssignable | ||||
From(beanClass)))); | ||||
} | } | |||
BeanInfo getBeanInfo() { | BeanInfo getBeanInfo() { | |||
return this.beanInfo; | return this.beanInfo; | |||
} | } | |||
Class<?> getBeanClass() { | Class<?> getBeanClass() { | |||
return this.beanInfo.getBeanDescriptor().getBeanClass(); | return this.beanInfo.getBeanDescriptor().getBeanClass(); | |||
} | } | |||
skipping to change at line 420 | skipping to change at line 420 | |||
// Same lenient fallback checking as in Property... | // Same lenient fallback checking as in Property... | |||
pd = this.propertyDescriptors.get(StringUtils.uncapitaliz e(name)); | pd = this.propertyDescriptors.get(StringUtils.uncapitaliz e(name)); | |||
if (pd == null) { | if (pd == null) { | |||
pd = this.propertyDescriptors.get(StringUtils.cap italize(name)); | pd = this.propertyDescriptors.get(StringUtils.cap italize(name)); | |||
} | } | |||
} | } | |||
return pd; | return pd; | |||
} | } | |||
PropertyDescriptor[] getPropertyDescriptors() { | PropertyDescriptor[] getPropertyDescriptors() { | |||
return this.propertyDescriptors.values().toArray(EMPTY_PROPERTY_D ESCRIPTOR_ARRAY); | return this.propertyDescriptors.values().toArray(PropertyDescript orUtils.EMPTY_PROPERTY_DESCRIPTOR_ARRAY); | |||
} | } | |||
private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class< ?> beanClass, PropertyDescriptor pd) { | private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class< ?> beanClass, PropertyDescriptor pd) { | |||
try { | try { | |||
return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(), | return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(), | |||
pd.getWriteMethod(), pd.getPropertyEditor Class()); | pd.getWriteMethod(), pd.getPropertyEditor Class()); | |||
} | } | |||
catch (IntrospectionException ex) { | catch (IntrospectionException ex) { | |||
throw new FatalBeanException("Failed to re-introspect cla ss [" + beanClass.getName() + "]", ex); | throw new FatalBeanException("Failed to re-introspect cla ss [" + beanClass.getName() + "]", ex); | |||
} | } | |||
End of changes. 6 change blocks. | ||||
15 lines changed or deleted | 17 lines changed or added |