18
18
19
19
import java .beans .BeanInfo ;
20
20
import java .beans .IntrospectionException ;
21
- import java .beans .Introspector ;
22
21
import java .beans .PropertyDescriptor ;
22
+ import java .beans .SimpleBeanInfo ;
23
23
import java .lang .reflect .Method ;
24
24
import java .lang .reflect .Modifier ;
25
25
import java .net .URL ;
26
26
import java .security .ProtectionDomain ;
27
+ import java .util .Collection ;
27
28
import java .util .Collections ;
28
29
import java .util .HashSet ;
29
30
import java .util .LinkedHashMap ;
36
37
import org .apache .commons .logging .Log ;
37
38
import org .apache .commons .logging .LogFactory ;
38
39
39
- import org .springframework .core .SpringProperties ;
40
40
import org .springframework .core .convert .TypeDescriptor ;
41
41
import org .springframework .core .io .support .SpringFactoriesLoader ;
42
42
import org .springframework .lang .Nullable ;
60
60
* <p>Note that for caching to work effectively, some preconditions need to be met:
61
61
* Prefer an arrangement where the Spring jars live in the same ClassLoader as the
62
62
* application classes, which allows for clean caching along with the application's
63
- * lifecycle in any case. For a web application, consider declaring a local
64
- * {@link org.springframework.web.util.IntrospectorCleanupListener} in {@code web.xml}
65
- * in case of a multi-ClassLoader layout, which will allow for effective caching as well.
63
+ * lifecycle in any case.
66
64
*
67
- * <p>In case of a non-clean ClassLoader arrangement without a cleanup listener having
68
- * been set up, this class will fall back to a weak-reference-based caching model that
69
- * recreates much-requested entries every time the garbage collector removed them. In
70
- * such a scenario, consider the {@link #IGNORE_BEANINFO_PROPERTY_NAME} system property.
65
+ * <p>As of 6.0, Spring's default introspection discovers basic JavaBeans properties
66
+ * through an efficient method reflection pass. For full JavaBeans introspection
67
+ * including indexed properties and all JDK-supported customizers, configure a
68
+ * {@code META-INF/spring.factories} file with the following content:
69
+ * {@code org.springframework.beans.BeanInfoFactory=org.springframework.beans.StandardBeanInfoFactory}
70
+ * For Spring 5.3 compatible extended introspection including non-void setter methods:
71
+ * {@code org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory}
71
72
*
72
73
* @author Rod Johnson
73
74
* @author Juergen Hoeller
78
79
*/
79
80
public final class CachedIntrospectionResults {
80
81
81
- /**
82
- * System property that instructs Spring to use the {@link Introspector#IGNORE_ALL_BEANINFO}
83
- * mode when calling the JavaBeans {@link Introspector}: "spring.beaninfo.ignore", with a
84
- * value of "true" skipping the search for {@code BeanInfo} classes (typically for scenarios
85
- * where no such classes are being defined for beans in the application in the first place).
86
- * <p>The default is "false", considering all {@code BeanInfo} metadata classes, like for
87
- * standard {@link Introspector#getBeanInfo(Class)} calls. Consider switching this flag to
88
- * "true" if you experience repeated ClassLoader access for non-existing {@code BeanInfo}
89
- * classes, in case such access is expensive on startup or on lazy loading.
90
- * <p>Note that such an effect may also indicate a scenario where caching doesn't work
91
- * effectively: Prefer an arrangement where the Spring jars live in the same ClassLoader
92
- * as the application classes, which allows for clean caching along with the application's
93
- * lifecycle in any case. For a web application, consider declaring a local
94
- * {@link org.springframework.web.util.IntrospectorCleanupListener} in {@code web.xml}
95
- * in case of a multi-ClassLoader layout, which will allow for effective caching as well.
96
- * @see Introspector#getBeanInfo(Class, int)
97
- */
98
- public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore" ;
99
-
100
82
private static final PropertyDescriptor [] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = {};
101
83
102
84
103
- private static final boolean shouldIntrospectorIgnoreBeaninfoClasses =
104
- SpringProperties .getFlag (IGNORE_BEANINFO_PROPERTY_NAME );
105
-
106
- /** Stores the BeanInfoFactory instances. */
107
85
private static final List <BeanInfoFactory > beanInfoFactories = SpringFactoriesLoader .loadFactories (
108
86
BeanInfoFactory .class , CachedIntrospectionResults .class .getClassLoader ());
109
87
@@ -241,7 +219,7 @@ private static boolean isUnderneathClassLoader(@Nullable ClassLoader candidate,
241
219
* Retrieve a {@link BeanInfo} descriptor for the given target class.
242
220
* @param beanClass the target class to introspect
243
221
* @return the resulting {@code BeanInfo} descriptor (never {@code null})
244
- * @throws IntrospectionException from the underlying {@link Introspector}
222
+ * @throws IntrospectionException from introspecting the given bean class
245
223
*/
246
224
private static BeanInfo getBeanInfo (Class <?> beanClass ) throws IntrospectionException {
247
225
for (BeanInfoFactory beanInfoFactory : beanInfoFactories ) {
@@ -250,9 +228,14 @@ private static BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionExce
250
228
return beanInfo ;
251
229
}
252
230
}
253
- return (shouldIntrospectorIgnoreBeaninfoClasses ?
254
- Introspector .getBeanInfo (beanClass , Introspector .IGNORE_ALL_BEANINFO ) :
255
- Introspector .getBeanInfo (beanClass ));
231
+
232
+ Collection <PropertyDescriptor > pds = PropertyDescriptorUtils .determineBasicProperties (beanClass );
233
+ return new SimpleBeanInfo () {
234
+ @ Override
235
+ public PropertyDescriptor [] getPropertyDescriptors () {
236
+ return pds .toArray (EMPTY_PROPERTY_DESCRIPTOR_ARRAY );
237
+ }
238
+ };
256
239
}
257
240
258
241
0 commit comments