Polishing

This commit is contained in:
Juergen Hoeller 2014-07-08 00:59:31 +02:00
parent 1115374188
commit 01264dc673
8 changed files with 78 additions and 69 deletions

View File

@ -22,9 +22,10 @@ import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/** /**
* Factory for Map that reads from a YAML source. YAML is a nice human-readable * Factory for a Map that reads from a YAML source. YAML is a nice human-readable
* format for configuration, and it has some useful hierarchical properties. It's * format for configuration, and it has some useful hierarchical properties. It's
* more or less a superset of JSON, so it has a lot of similar features. If * more or less a superset of JSON, so it has a lot of similar features. If
* multiple resources are provided the later ones will override entries in the * multiple resources are provided the later ones will override entries in the
@ -36,7 +37,6 @@ import org.springframework.beans.factory.FactoryBean;
* bar: * bar:
* one: two * one: two
* three: four * three: four
*
* </pre> * </pre>
* *
* plus (later in the list) * plus (later in the list)
@ -46,7 +46,6 @@ import org.springframework.beans.factory.FactoryBean;
* bar: * bar:
* one: 2 * one: 2
* five: six * five: six
*
* </pre> * </pre>
* *
* results in an effective input of * results in an effective input of
@ -57,7 +56,6 @@ import org.springframework.beans.factory.FactoryBean;
* one: 2 * one: 2
* three: four * three: four
* five: six * five: six
*
* </pre> * </pre>
* *
* Note that the value of "foo" in the first document is not simply replaced * Note that the value of "foo" in the first document is not simply replaced
@ -66,35 +64,36 @@ import org.springframework.beans.factory.FactoryBean;
* @author Dave Syer * @author Dave Syer
* @since 4.1 * @since 4.1
*/ */
public class YamlMapFactoryBean extends YamlProcessor implements public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
FactoryBean<Map<String, Object>> {
private boolean singleton = true; private boolean singleton = true;
private Map<String, Object> singletonInstance; private Map<String, Object> map;
/** /**
* Set whether a shared 'singleton' Map instance should be * Set if a singleton should be created, or a new object on each request
* created, or rather a new Map instance on each request. * otherwise. Default is {@code true} (a singleton).
* <p>Default is "true" (a shared singleton).
*/ */
public final void setSingleton(boolean singleton) { public void setSingleton(boolean singleton) {
this.singleton = singleton; this.singleton = singleton;
} }
@Override @Override
public final boolean isSingleton() { public boolean isSingleton() {
return this.singleton; return this.singleton;
} }
@Override
public void afterPropertiesSet() {
if (isSingleton()) {
this.map = createMap();
}
}
@Override @Override
public Map<String, Object> getObject() { public Map<String, Object> getObject() {
if (!this.singleton || this.singletonInstance == null) { return (this.map != null ? this.map : createMap());
this.singletonInstance = createProperties();
}
return this.singletonInstance;
} }
@Override @Override
@ -102,6 +101,7 @@ public class YamlMapFactoryBean extends YamlProcessor implements
return Map.class; return Map.class;
} }
/** /**
* Template method that subclasses may override to construct the object * Template method that subclasses may override to construct the object
* returned by this factory. The default implementation returns the * returned by this factory. The default implementation returns the
@ -111,7 +111,7 @@ public class YamlMapFactoryBean extends YamlProcessor implements
* @return the object returned by this factory * @return the object returned by this factory
* @see #process(java.util.Map, MatchCallback) * @see #process(java.util.Map, MatchCallback)
*/ */
protected Map<String, Object> createProperties() { protected Map<String, Object> createMap() {
final Map<String, Object> result = new LinkedHashMap<String, Object>(); final Map<String, Object> result = new LinkedHashMap<String, Object>();
process(new MatchCallback() { process(new MatchCallback() {
@Override @Override
@ -129,8 +129,7 @@ public class YamlMapFactoryBean extends YamlProcessor implements
Object value = entry.getValue(); Object value = entry.getValue();
Object existing = output.get(key); Object existing = output.get(key);
if (value instanceof Map && existing instanceof Map) { if (value instanceof Map && existing instanceof Map) {
Map<String, Object> result = new LinkedHashMap<String, Object>( Map<String, Object> result = new LinkedHashMap<String, Object>((Map) existing);
(Map) existing);
merge(result, (Map) value); merge(result, (Map) value);
output.put(key, result); output.put(key, result);
} }

View File

@ -53,6 +53,7 @@ public abstract class YamlProcessor {
private boolean matchDefault = true; private boolean matchDefault = true;
/** /**
* A map of document matchers allowing callers to selectively use only * A map of document matchers allowing callers to selectively use only
* some of the documents in a YAML resource. In YAML documents are * some of the documents in a YAML resource. In YAML documents are
@ -112,10 +113,11 @@ public abstract class YamlProcessor {
* Set locations of YAML {@link Resource resources} to be loaded. * Set locations of YAML {@link Resource resources} to be loaded.
* @see ResolutionMethod * @see ResolutionMethod
*/ */
public void setResources(Resource[] resources) { public void setResources(Resource... resources) {
this.resources = (resources == null ? null : resources.clone()); this.resources = (resources == null ? null : resources.clone());
} }
/** /**
* Provide an opportunity for subclasses to process the Yaml parsed from the supplied * Provide an opportunity for subclasses to process the Yaml parsed from the supplied
* resources. Each resource is parsed in turn and the documents inside checked against * resources. Each resource is parsed in turn and the documents inside checked against
@ -157,17 +159,16 @@ public abstract class YamlProcessor {
catch (IOException ex) { catch (IOException ex) {
handleProcessError(resource, ex); handleProcessError(resource, ex);
} }
return count > 0; return (count > 0);
} }
private void handleProcessError(Resource resource, IOException ex) { private void handleProcessError(Resource resource, IOException ex) {
if (this.resolutionMethod != ResolutionMethod.FIRST_FOUND if (this.resolutionMethod != ResolutionMethod.FIRST_FOUND &&
&& this.resolutionMethod != ResolutionMethod.OVERRIDE_AND_IGNORE) { this.resolutionMethod != ResolutionMethod.OVERRIDE_AND_IGNORE) {
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
if (this.logger.isWarnEnabled()) { if (this.logger.isWarnEnabled()) {
this.logger.warn("Could not load map from " + resource + ": " this.logger.warn("Could not load map from " + resource + ": " + ex.getMessage());
+ ex.getMessage());
} }
} }
@ -200,7 +201,6 @@ public abstract class YamlProcessor {
} }
private boolean process(Map<String, Object> map, MatchCallback callback) { private boolean process(Map<String, Object> map, MatchCallback callback) {
Properties properties = new Properties(); Properties properties = new Properties();
assignProperties(properties, map, null); assignProperties(properties, map, null);
@ -238,8 +238,7 @@ public abstract class YamlProcessor {
return false; return false;
} }
private void assignProperties(Properties properties, Map<String, Object> input, private void assignProperties(Properties properties, Map<String, Object> input, String path) {
String path) {
for (Entry<String, Object> entry : input.entrySet()) { for (Entry<String, Object> entry : input.entrySet()) {
String key = entry.getKey(); String key = entry.getKey();
if (StringUtils.hasText(path)) { if (StringUtils.hasText(path)) {
@ -276,6 +275,7 @@ public abstract class YamlProcessor {
} }
} }
/** /**
* Callback interface used to process properties in a resulting map. * Callback interface used to process properties in a resulting map.
*/ */
@ -287,9 +287,9 @@ public abstract class YamlProcessor {
* @param map a mutable result map * @param map a mutable result map
*/ */
void process(Properties properties, Map<String, Object> map); void process(Properties properties, Map<String, Object> map);
} }
/** /**
* Strategy interface used to test if properties match. * Strategy interface used to test if properties match.
*/ */
@ -301,9 +301,9 @@ public abstract class YamlProcessor {
* @return the status of the match. * @return the status of the match.
*/ */
MatchStatus matches(Properties properties); MatchStatus matches(Properties properties);
} }
/** /**
* Status returned from {@link DocumentMatcher#matches(java.util.Properties)} * Status returned from {@link DocumentMatcher#matches(java.util.Properties)}
*/ */
@ -332,6 +332,7 @@ public abstract class YamlProcessor {
} }
} }
/** /**
* Method to use for resolving resources. * Method to use for resolving resources.
*/ */

View File

@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
/** /**
* Factory for Java Properties that reads from a YAML source. YAML is a nice * Factory for Java Properties that reads from a YAML source. YAML is a nice
@ -57,7 +58,7 @@ import org.springframework.beans.factory.FactoryBean;
* - foo.bar.com * - foo.bar.com
* </pre> * </pre>
* *
* becomes java Properties like this: * becomes Java Properties like this:
* *
* <pre class="code"> * <pre class="code">
* servers=dev.bar.com,foo.bar.com * servers=dev.bar.com,foo.bar.com
@ -65,42 +66,40 @@ import org.springframework.beans.factory.FactoryBean;
* servers[1]=foo.bar.com * servers[1]=foo.bar.com
* </pre> * </pre>
* *
* Can create a singleton or a new object on each request. Default is
* a singleton.
*
* @author Dave Syer * @author Dave Syer
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 4.1 * @since 4.1
*/ */
public class YamlPropertiesFactoryBean extends YamlProcessor implements public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
FactoryBean<Properties> {
private boolean singleton = true; private boolean singleton = true;
private Properties singletonInstance; private Properties properties;
/** /**
* Set whether a shared 'singleton' Properties instance should be * Set if a singleton should be created, or a new object on each request
* created, or rather a new Properties instance on each request. * otherwise. Default is {@code true} (a singleton).
* <p>Default is "true" (a shared singleton).
*/ */
public final void setSingleton(boolean singleton) { public void setSingleton(boolean singleton) {
this.singleton = singleton; this.singleton = singleton;
} }
@Override @Override
public final boolean isSingleton() { public boolean isSingleton() {
return this.singleton; return this.singleton;
} }
@Override
public void afterPropertiesSet() {
if (isSingleton()) {
this.properties = createProperties();
}
}
@Override @Override
public final Properties getObject() { public Properties getObject() {
if (!this.singleton || this.singletonInstance == null) { return (this.properties != null ? this.properties : createProperties());
this.singletonInstance = createProperties();
}
return this.singletonInstance;
} }
@Override @Override

View File

@ -22,10 +22,10 @@ import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.DefaultOrderProviderComparator; import org.springframework.core.annotation.DefaultOrderProviderComparator;
/** /**
* The default {@link Comparator} to use to order dependencies. Extend * The default {@link Comparator} to use to order dependencies. Extends from
* from {@link DefaultOrderProviderComparator} so that the bean factory * {@link DefaultOrderProviderComparator} so that the bean factory has the ability
* has the ability to provide an {@link org.springframework.core.annotation.OrderProvider} * to provide an {@link org.springframework.core.annotation.OrderProvider} that
* that is aware of more bean metadata, if any. * is aware of more bean metadata, if any.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 4.1 * @since 4.1
@ -40,19 +40,22 @@ public class DefaultDependencyComparator extends DefaultOrderProviderComparator
*/ */
public static final DefaultDependencyComparator INSTANCE = new DefaultDependencyComparator(); public static final DefaultDependencyComparator INSTANCE = new DefaultDependencyComparator();
private final Comparator<Object> comparator; private final Comparator<Object> comparator;
public DefaultDependencyComparator() {
this.comparator = AnnotationAwareOrderComparator.INSTANCE;
}
public DefaultDependencyComparator(Comparator<Object> comparator) { public DefaultDependencyComparator(Comparator<Object> comparator) {
this.comparator = comparator; this.comparator = comparator;
} }
public DefaultDependencyComparator() {
this(AnnotationAwareOrderComparator.INSTANCE);
}
@Override @Override
public int compare(Object o1, Object o2) { public int compare(Object o1, Object o2) {
return comparator.compare(o1, o2); return this.comparator.compare(o1, o2);
} }
} }

View File

@ -47,21 +47,24 @@ import org.springframework.core.annotation.OrderProvider;
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 4.1 * @since 4.1
*/ */
public class FactoryAwareOrderProvider implements OrderProvider { class FactoryAwareOrderProvider implements OrderProvider {
private final Map<Object, String> instancesToBeanNames; private final Map<Object, String> instancesToBeanNames;
private final ConfigurableListableBeanFactory beanFactory; private final ConfigurableListableBeanFactory beanFactory;
public FactoryAwareOrderProvider(Map<Object, String> instancesToBeanNames, public FactoryAwareOrderProvider(Map<Object, String> instancesToBeanNames,
ConfigurableListableBeanFactory beanFactory) { ConfigurableListableBeanFactory beanFactory) {
this.instancesToBeanNames = instancesToBeanNames; this.instancesToBeanNames = instancesToBeanNames;
this.beanFactory = beanFactory; this.beanFactory = beanFactory;
} }
@Override @Override
public Integer getOrder(Object obj) { public Integer getOrder(Object obj) {
Method factoryMethod = getFactoryMethod(instancesToBeanNames.get(obj)); Method factoryMethod = getFactoryMethod(this.instancesToBeanNames.get(obj));
if (factoryMethod != null) { if (factoryMethod != null) {
Order order = AnnotationUtils.getAnnotation(factoryMethod, Order.class); Order order = AnnotationUtils.getAnnotation(factoryMethod, Order.class);
if (order != null) { if (order != null) {

View File

@ -407,7 +407,9 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
if (this.server == null) { if (this.server == null) {
this.server = JmxUtils.locateMBeanServer(); this.server = JmxUtils.locateMBeanServer();
} }
register(); // TODO: to be replaced with some ContextRefreshedEvent-like callback
// TODO: to be replaced with some ContextRefreshedEvent-like callback
register();
} }
/** /**
@ -766,22 +768,22 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
protected DynamicMBean adaptMBeanIfPossible(Object bean) throws JMException { protected DynamicMBean adaptMBeanIfPossible(Object bean) throws JMException {
Class<?> targetClass = AopUtils.getTargetClass(bean); Class<?> targetClass = AopUtils.getTargetClass(bean);
if (targetClass != bean.getClass()) { if (targetClass != bean.getClass()) {
Class<Object> ifc = (Class<Object>) JmxUtils.getMXBeanInterface(targetClass); Class<?> ifc = JmxUtils.getMXBeanInterface(targetClass);
if (ifc != null) { if (ifc != null) {
if (!(ifc.isInstance(bean))) { if (!ifc.isInstance(bean)) {
throw new NotCompliantMBeanException("Managed bean [" + bean + throw new NotCompliantMBeanException("Managed bean [" + bean +
"] has a target class with an MXBean interface but does not expose it in the proxy"); "] has a target class with an MXBean interface but does not expose it in the proxy");
} }
return new StandardMBean(bean, ifc, true); return new StandardMBean(bean, ((Class<Object>) ifc), true);
} }
else { else {
ifc = (Class<Object>) JmxUtils.getMBeanInterface(targetClass); ifc = JmxUtils.getMBeanInterface(targetClass);
if (ifc != null) { if (ifc != null) {
if (!(ifc.isInstance(bean))) { if (!ifc.isInstance(bean)) {
throw new NotCompliantMBeanException("Managed bean [" + bean + throw new NotCompliantMBeanException("Managed bean [" + bean +
"] has a target class with an MBean interface but does not expose it in the proxy"); "] has a target class with an MBean interface but does not expose it in the proxy");
} }
return new StandardMBean(bean, ifc); return new StandardMBean(bean, ((Class<Object>) ifc));
} }
} }
} }

View File

@ -38,6 +38,7 @@ public class DefaultOrderProviderComparator implements OrderProviderComparator {
*/ */
public static final DefaultOrderProviderComparator INSTANCE = new DefaultOrderProviderComparator(); public static final DefaultOrderProviderComparator INSTANCE = new DefaultOrderProviderComparator();
@Override @Override
public void sortList(List<?> items, OrderProvider orderProvider) { public void sortList(List<?> items, OrderProvider orderProvider) {
Collections.sort(items, new OrderProviderAwareComparator(orderProvider)); Collections.sort(items, new OrderProviderAwareComparator(orderProvider));
@ -53,7 +54,7 @@ public class DefaultOrderProviderComparator implements OrderProviderComparator {
private final OrderProvider orderProvider; private final OrderProvider orderProvider;
private OrderProviderAwareComparator(OrderProvider orderProvider) { public OrderProviderAwareComparator(OrderProvider orderProvider) {
this.orderProvider = orderProvider; this.orderProvider = orderProvider;
} }

View File

@ -21,8 +21,8 @@ import java.lang.annotation.Annotation;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
/** /**
* General utility for determining the order of an object based * General utility for determining the order of an object based on its type declaration.
* on its type declaration. * Handles Spring's {@link Order} annotation as well as {@link javax.annotation.Priority}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 4.1 * @since 4.1
@ -36,6 +36,7 @@ public abstract class OrderUtils {
private static final boolean priorityPresent = private static final boolean priorityPresent =
ClassUtils.isPresent(PRIORITY_ANNOTATION_CLASS_NAME, OrderUtils.class.getClassLoader()); ClassUtils.isPresent(PRIORITY_ANNOTATION_CLASS_NAME, OrderUtils.class.getClassLoader());
/** /**
* Return the order on the specified {@code type} or the specified * Return the order on the specified {@code type} or the specified
* default value if none can be found. * default value if none can be found.
@ -56,8 +57,8 @@ public abstract class OrderUtils {
} }
/** /**
* Return the value of the {@code javax.annotation.Priority} annotation set on the * Return the value of the {@code javax.annotation.Priority} annotation set
* specified type or {@code null} if none is set. * on the specified type or {@code null} if none is set.
* @param type the type to handle * @param type the type to handle
* @return the priority value if the annotation is set, {@code null} otherwise * @return the priority value if the annotation is set, {@code null} otherwise
*/ */