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
|
||||
* 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
|
||||
|
@ -59,11 +71,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
|
||||
|
@ -79,6 +113,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.
|
||||
|
@ -238,7 +287,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…
Reference in New Issue