Introduced SpringProperties class and optional "spring.properties" file

This in particular allows for specifying "spring.getenv.ignore" and "spring.beaninfo.ignore" in a local way within the application, in case that JVM-level system properties are locked.

Issue: SPR-9014
Issue: SPR-11297
This commit is contained in:
Juergen Hoeller
2014-01-24 16:22:02 +01:00
parent 6151e6d12a
commit 8543b91c50
6 changed files with 203 additions and 61 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -492,20 +492,21 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
public Object convertForProperty(Object value, String propertyName) throws TypeMismatchException {
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
if (pd == null) {
throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
"No property '" + propertyName + "' found");
}
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
if (td == null) {
td = new TypeDescriptor(property(pd));
cachedIntrospectionResults.putTypeDescriptor(pd, td);
cachedIntrospectionResults.addTypeDescriptor(pd, td);
}
return convertForProperty(propertyName, null, value, pd, td);
}
private Object convertForProperty(String propertyName, Object oldValue, Object newValue, PropertyDescriptor pd, TypeDescriptor td)
throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, pd.getPropertyType(), td);
}

View File

@@ -22,7 +22,6 @@ import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -30,10 +29,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.SpringProperties;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.util.ClassUtils;
@@ -116,17 +117,7 @@ public class CachedIntrospectionResults {
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;
shouldIntrospectorIgnoreBeaninfoClasses = SpringProperties.getFlag(IGNORE_BEANINFO_PROPERTY_NAME);
}
@@ -298,16 +289,19 @@ public class CachedIntrospectionResults {
}
this.beanInfo = beanInfo;
// Immediately remove class from Introspector cache, to allow for proper
// garbage collection on class loader shutdown - we cache it here anyway,
// in a GC-friendly manner. In contrast to CachedIntrospectionResults,
// Introspector does not use WeakReferences as values of its WeakHashMap!
Class<?> classToFlush = beanClass;
do {
Introspector.flushFromCaches(classToFlush);
classToFlush = classToFlush.getSuperclass();
// Only bother with flushFromCaches if the Introspector actually cached...
if (!shouldIntrospectorIgnoreBeaninfoClasses) {
// Immediately remove class from Introspector cache, to allow for proper
// garbage collection on class loader shutdown - we cache it here anyway,
// in a GC-friendly manner. In contrast to CachedIntrospectionResults,
// Introspector does not use WeakReferences as values of its WeakHashMap!
Class<?> classToFlush = beanClass;
do {
Introspector.flushFromCaches(classToFlush);
classToFlush = classToFlush.getSuperclass();
}
while (classToFlush != null);
}
while (classToFlush != null);
if (logger.isTraceEnabled()) {
logger.trace("Caching PropertyDescriptors for class [" + beanClass.getName() + "]");
@@ -332,7 +326,7 @@ public class CachedIntrospectionResults {
this.propertyDescriptorCache.put(pd.getName(), pd);
}
this.typeDescriptorCache = new HashMap<PropertyDescriptor, TypeDescriptor>();
this.typeDescriptorCache = new ConcurrentHashMap<PropertyDescriptor, TypeDescriptor>();
}
catch (IntrospectionException ex) {
throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
@@ -381,12 +375,12 @@ public class CachedIntrospectionResults {
}
}
void addTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) {
this.typeDescriptorCache.put(pd, td);
}
TypeDescriptor getTypeDescriptor(PropertyDescriptor pd) {
return this.typeDescriptorCache.get(pd);
}
void putTypeDescriptor(PropertyDescriptor pd, TypeDescriptor td) {
this.typeDescriptorCache.put(pd, td);
}
}

View File

@@ -21,6 +21,7 @@ import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.core.Constants;
import org.springframework.core.SpringProperties;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.util.PropertyPlaceholderHelper;
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
@@ -84,7 +85,7 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;
private boolean searchSystemEnvironment =
!"true".equalsIgnoreCase(System.getProperty(AbstractEnvironment.IGNORE_GETENV_PROPERTY_NAME));
!SpringProperties.getFlag(AbstractEnvironment.IGNORE_GETENV_PROPERTY_NAME);
/**