Browse Source

Introduced "spring.beaninfo.ignore" system property for optimized Introspector usage

Issue: SPR-9014
(cherry picked from commit f88cbda)
pull/432/head
Juergen Hoeller 11 years ago
parent
commit
240819f955
  1. 57
      spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java

57
spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java

@ -52,6 +52,18 @@ import org.springframework.util.StringUtils; @@ -52,6 +52,18 @@ import org.springframework.util.StringUtils;
* implements the factory design pattern, using a private constructor and
* a static {@link #forClass(Class)} factory method to obtain instances.
*
* <p>Note that for caching to work effectively, some preconditions need to be met:
* Prefer an arrangement where the Spring jars live in the same ClassLoader 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 local
* {@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.
*
* <p>In case of a non-clean ClassLoader arrangement without a cleanup listener having
* been set up, this class will fall back to a weak-reference-based caching model that
* recreates much-requested entries every time the garbage collector removed them. In
* such a scenario, consider the {@link #IGNORE_BEANINFO_PROPERTY_NAME} system property.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 05 May 2001
@ -61,11 +73,33 @@ import org.springframework.util.StringUtils; @@ -61,11 +73,33 @@ import org.springframework.util.StringUtils;
*/
public class CachedIntrospectionResults {
/**
* System property that instructs Spring to use the {@link Introspector#IGNORE_ALL_BEANINFO}
* mode when calling the JavaBeans {@link Introspector}: "spring.beaninfo.ignore", with a
* value of "true" skipping the search for {@code BeanInfo} classes (typically for scenarios
* where no such classes are being defined for beans in the application in the first place).
* <p>Default is "false", considering all {@code BeanInfo} metadata classes, like for
* standard {@link Introspector#getBeanInfo(Class)} calls. Consider switching this flag to
* "true" if you experience repeated ClassLoader access for non-existing {@code BeanInfo}
* classes, in case such access is expensive on startup or on lazy loading.
* <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 same ClassLoader
* 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 local
* {@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.
* @see Introspector#getBeanInfo(Class, int)
*/
public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";
private static final Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses;
/** Stores the BeanInfoFactory instances */
private static List<BeanInfoFactory> beanInfoFactories =
SpringFactoriesLoader.loadFactories(BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
/**
* Set of ClassLoaders that this CachedIntrospectionResults class will always
@ -81,6 +115,21 @@ public class CachedIntrospectionResults { @@ -81,6 +115,21 @@ public class CachedIntrospectionResults {
static final Map<Class<?>, Object> classCache = new WeakHashMap<Class<?>, Object>();
static {
boolean ignoreValue;
try {
ignoreValue = "true".equalsIgnoreCase(System.getProperty(IGNORE_BEANINFO_PROPERTY_NAME));
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not obtain system property '" + IGNORE_BEANINFO_PROPERTY_NAME + "': " + ex);
}
ignoreValue = false;
}
shouldIntrospectorIgnoreBeaninfoClasses = ignoreValue;
}
/**
* Accept the given ClassLoader as cache-safe, even if its classes would
* not qualify as cache-safe in this CachedIntrospectionResults class.
@ -243,7 +292,9 @@ public class CachedIntrospectionResults { @@ -243,7 +292,9 @@ public class CachedIntrospectionResults {
}
if (beanInfo == null) {
// If none of the factories supported the class, fall back to the default
beanInfo = Introspector.getBeanInfo(beanClass);
beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
Introspector.getBeanInfo(beanClass));
}
this.beanInfo = beanInfo;

Loading…
Cancel
Save