Introduced "spring.beaninfo.ignore" system property for optimized Introspector usage
Issue: SPR-9014
This commit is contained in:
parent
c48da0d9a4
commit
f88cbda6ef
|
@ -50,6 +50,18 @@ import org.springframework.util.StringUtils;
|
||||||
* implements the factory design pattern, using a private constructor and
|
* implements the factory design pattern, using a private constructor and
|
||||||
* a static {@link #forClass(Class)} factory method to obtain instances.
|
* 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 Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 05 May 2001
|
* @since 05 May 2001
|
||||||
|
@ -59,11 +71,33 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
public class CachedIntrospectionResults {
|
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 Log logger = LogFactory.getLog(CachedIntrospectionResults.class);
|
||||||
|
|
||||||
|
private static final boolean shouldIntrospectorIgnoreBeaninfoClasses;
|
||||||
|
|
||||||
/** Stores the BeanInfoFactory instances */
|
/** Stores the BeanInfoFactory instances */
|
||||||
private static List<BeanInfoFactory> beanInfoFactories =
|
private static List<BeanInfoFactory> beanInfoFactories = SpringFactoriesLoader.loadFactories(
|
||||||
SpringFactoriesLoader.loadFactories(BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
|
BeanInfoFactory.class, CachedIntrospectionResults.class.getClassLoader());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of ClassLoaders that this CachedIntrospectionResults class will always
|
* Set of ClassLoaders that this CachedIntrospectionResults class will always
|
||||||
|
@ -79,6 +113,21 @@ public class CachedIntrospectionResults {
|
||||||
static final Map<Class<?>, Object> classCache = new WeakHashMap<Class<?>, Object>();
|
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
|
* Accept the given ClassLoader as cache-safe, even if its classes would
|
||||||
* not qualify as cache-safe in this CachedIntrospectionResults class.
|
* not qualify as cache-safe in this CachedIntrospectionResults class.
|
||||||
|
@ -238,7 +287,9 @@ public class CachedIntrospectionResults {
|
||||||
}
|
}
|
||||||
if (beanInfo == null) {
|
if (beanInfo == null) {
|
||||||
// If none of the factories supported the class, fall back to the default
|
// 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;
|
this.beanInfo = beanInfo;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue