Polishing

This commit is contained in:
Juergen Hoeller
2014-04-29 23:39:17 +02:00
parent 3cb1cb5d2f
commit a5606a6c46
9 changed files with 268 additions and 140 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -25,6 +25,7 @@ import java.util.WeakHashMap;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* General utility methods for working with annotations, handling bridge methods (which the compiler
@@ -60,8 +61,8 @@ public abstract class AnnotationUtils {
* Method, Constructor or Field. Meta-annotations will be searched if the annotation
* is not declared locally on the supplied element.
* @param ae the Method, Constructor or Field from which to get the annotation
* @param annotationType the annotation class to look for, both locally and as a meta-annotation
* @return the matching annotation or {@code null} if not found
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @return the matching annotation, or {@code null} if none found
* @since 3.1
*/
public static <T extends Annotation> T getAnnotation(AnnotatedElement ae, Class<T> annotationType) {
@@ -92,7 +93,7 @@ public abstract class AnnotationUtils {
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
* @param annotationType the annotation type to look for
* @return the annotations found
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
*/
@@ -115,8 +116,8 @@ public abstract class AnnotationUtils {
* traversing its super methods if no annotation can be found on the given method itself.
* <p>Annotations on methods are not inherited by default, so we need to handle this explicitly.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
* @return the annotation found, or {@code null} if none found
* @param annotationType the annotation type to look for
* @return the annotation found, or {@code null} if none
*/
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
A annotation = getAnnotation(method, annotationType);
@@ -192,7 +193,7 @@ public abstract class AnnotationUtils {
* with the interfaces that the superclass declares. Recursing up through the entire superclass
* hierarchy if no match is found.
* @param clazz the class to look for annotations on
* @param annotationType the annotation class to look for
* @param annotationType the annotation type to look for
* @return the annotation found, or {@code null} if none found
*/
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
@@ -215,11 +216,11 @@ public abstract class AnnotationUtils {
}
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass == null || superClass.equals(Object.class)) {
Class<?> superclass = clazz.getSuperclass();
if (superclass == null || superclass.equals(Object.class)) {
return null;
}
return findAnnotation(superClass, annotationType);
return findAnnotation(superclass, annotationType);
}
/**
@@ -232,9 +233,8 @@ public abstract class AnnotationUtils {
* <p>The standard {@link Class} API does not provide a mechanism for determining which class
* in an inheritance hierarchy actually declares an {@link Annotation}, so we need to handle
* this explicitly.
* @param annotationType the Class object corresponding to the annotation type
* @param clazz the Class object corresponding to the class on which to check for the annotation,
* or {@code null}
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @param clazz the class on which to check for the annotation (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy of the specified {@code clazz}
* which declares an annotation for the specified {@code annotationType}, or {@code null}
* if not found
@@ -248,8 +248,10 @@ public abstract class AnnotationUtils {
if (clazz == null || clazz.equals(Object.class)) {
return null;
}
return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz : findAnnotationDeclaringClass(
annotationType, clazz.getSuperclass());
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
return clazz;
}
return findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
}
/**
@@ -413,14 +415,13 @@ public abstract class AnnotationUtils {
}
if (nestedAnnotationsAsMap && value instanceof Annotation) {
attrs.put(method.getName(),
getAnnotationAttributes((Annotation) value, classValuesAsString, nestedAnnotationsAsMap));
getAnnotationAttributes((Annotation) value, classValuesAsString, true));
}
else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
Annotation[] realAnnotations = (Annotation[]) value;
AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
for (int i = 0; i < realAnnotations.length; i++) {
mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], classValuesAsString,
nestedAnnotationsAsMap);
mappedAnnotations[i] = getAnnotationAttributes(realAnnotations[i], classValuesAsString, true);
}
attrs.put(method.getName(), mappedAnnotations);
}
@@ -456,7 +457,8 @@ public abstract class AnnotationUtils {
*/
public static Object getValue(Annotation annotation, String attributeName) {
try {
Method method = annotation.annotationType().getDeclaredMethod(attributeName, new Class[0]);
Method method = annotation.annotationType().getDeclaredMethod(attributeName);
ReflectionUtils.makeAccessible(method);
return method.invoke(annotation);
}
catch (Exception ex) {
@@ -506,8 +508,7 @@ public abstract class AnnotationUtils {
*/
public static Object getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
try {
Method method = annotationType.getDeclaredMethod(attributeName, new Class[0]);
return method.getDefaultValue();
return annotationType.getDeclaredMethod(attributeName).getDefaultValue();
}
catch (Exception ex) {
return null;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2014 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.
@@ -18,6 +18,7 @@ package org.springframework.core.env;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
/**
@@ -53,21 +54,22 @@ public abstract class EnumerablePropertySource<T> extends PropertySource<T> {
super(name, source);
}
/**
* Return the names of all properties contained by the {@linkplain #getSource()
* source} object (never {@code null}).
* Return the names of all properties contained by the
* {@linkplain #getSource() source} object (never {@code null}).
*/
public abstract String[] getPropertyNames();
/**
* Return whether this {@code PropertySource} contains a property with the given name.
* <p>This implementation checks for the presence of the given name within
* the {@link #getPropertyNames()} array.
* @param name the property to find
* <p>This implementation checks for the presence of the given name within the
* {@link #getPropertyNames()} array.
* @param name the name of the property to find
*/
public boolean containsProperty(String name) {
Assert.notNull(name, "property name must not be null");
for (String candidate : this.getPropertyNames()) {
Assert.notNull(name, "Property name must not be null");
for (String candidate : getPropertyNames()) {
if (candidate.equals(name)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("PropertySource [%s] contains '%s'", getName(), name));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2014 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.
@@ -18,7 +18,9 @@ package org.springframework.core.env;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Abstract base class representing a source of name/value property pairs. The underlying
@@ -55,12 +57,13 @@ import org.springframework.util.Assert;
*/
public abstract class PropertySource<T> {
protected final Log logger = LogFactory.getLog(this.getClass());
protected final Log logger = LogFactory.getLog(getClass());
protected final String name;
protected final T source;
/**
* Create a new {@code PropertySource} with the given name and source object.
*/
@@ -74,15 +77,15 @@ public abstract class PropertySource<T> {
/**
* Create a new {@code PropertySource} with the given name and with a new {@code Object}
* instance as the underlying source.
* <p>Often useful in testing scenarios when creating
* anonymous implementations that never query an actual source, but rather return
* hard-coded values.
* <p>Often useful in testing scenarios when creating anonymous implementations that
* never query an actual source but rather return hard-coded values.
*/
@SuppressWarnings("unchecked")
public PropertySource(String name) {
this(name, (T) new Object());
}
/**
* Return the name of this {@code PropertySource}
*/
@@ -94,91 +97,75 @@ public abstract class PropertySource<T> {
* Return the underlying source object for this {@code PropertySource}.
*/
public T getSource() {
return source;
return this.source;
}
/**
* Return whether this {@code PropertySource} contains the given name.
* <p>This implementation simply checks for a null return value
* from {@link #getProperty(String)}. Subclasses may wish to
* implement a more efficient algorithm if possible.
* <p>This implementation simply checks for a {@code null} return value
* from {@link #getProperty(String)}. Subclasses may wish to implement
* a more efficient algorithm if possible.
* @param name the property name to find
*/
public boolean containsProperty(String name) {
return this.getProperty(name) != null;
return (getProperty(name) != null);
}
/**
* Return the value associated with the given name, {@code null} if not found.
* Return the value associated with the given name,
* or {@code null} if not found.
* @param name the property to find
* @see PropertyResolver#getRequiredProperty(String)
*/
public abstract Object getProperty(String name);
/**
* Return a hashcode derived from the {@code name} property of this {@code PropertySource}
* object.
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
return result;
}
/**
* This {@code PropertySource} object is equal to the given object if:
* <ul>
* <li>they are the same instance
* <li>the {@code name} properties for both objects are equal
* <li>they are the same instance
* <li>the {@code name} properties for both objects are equal
* </ul>
*
* <P>No properties other than {@code name} are evaluated.
* <p>No properties other than {@code name} are evaluated.
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof PropertySource))
return false;
PropertySource<?> other = (PropertySource<?>) obj;
if (this.name == null) {
if (other.name != null)
return false;
} else if (!this.name.equals(other.name))
return false;
return true;
return (this == obj || (obj instanceof PropertySource &&
ObjectUtils.nullSafeEquals(this.name, ((PropertySource<?>) obj).name)));
}
/**
* Return a hash code derived from the {@code name} property
* of this {@code PropertySource} object.
*/
@Override
public int hashCode() {
return ObjectUtils.nullSafeHashCode(this.name);
}
/**
* Produce concise output (type and name) if the current log level does not include
* debug. If debug is enabled, produce verbose output including hashcode of the
* debug. If debug is enabled, produce verbose output including the hash code of the
* PropertySource instance and every name/value property pair.
*
* This variable verbosity is useful as a property source such as system properties
* <p>This variable verbosity is useful as a property source such as system properties
* or environment variables may contain an arbitrary number of property pairs,
* potentially leading to difficult to read exception and log messages.
*
* @see Log#isDebugEnabled()
*/
@Override
public String toString() {
if (logger.isDebugEnabled()) {
return String.format("%s@%s [name='%s', properties=%s]",
this.getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
getClass().getSimpleName(), System.identityHashCode(this), this.name, this.source);
}
else {
return String.format("%s [name='%s']", getClass().getSimpleName(), this.name);
}
return String.format("%s [name='%s']",
this.getClass().getSimpleName(), this.name);
}
/**
* Return a {@code PropertySource} implementation intended for collection comparison purposes only.
*
* <p>Primarily for internal use, but given a collection of {@code PropertySource} objects, may be
* used as follows:
* <pre class="code">
@@ -189,11 +176,9 @@ public abstract class PropertySource<T> {
* assert sources.contains(PropertySource.named("sourceB"));
* assert !sources.contains(PropertySource.named("sourceC"));
* }</pre>
*
* The returned {@code PropertySource} will throw {@code UnsupportedOperationException}
* if any methods other than {@code equals(Object)}, {@code hashCode()}, and {@code toString()}
* are called.
*
* @param name the name of the comparison {@code PropertySource} to be created and returned.
*/
public static PropertySource<?> named(String name) {
@@ -209,7 +194,6 @@ public abstract class PropertySource<T> {
* {@code ApplicationContext}. In such cases, a stub should be used to hold the
* intended default position/order of the property source, then be replaced
* during context refresh.
*
* @see org.springframework.context.support.AbstractApplicationContext#initPropertySources()
* @see org.springframework.web.context.support.StandardServletEnvironment
* @see org.springframework.web.context.support.ServletContextPropertySource
@@ -221,7 +205,7 @@ public abstract class PropertySource<T> {
}
/**
* Always return {@code null}.
* Always returns {@code null}.
*/
@Override
public String getProperty(String name) {
@@ -236,8 +220,7 @@ public abstract class PropertySource<T> {
static class ComparisonPropertySource extends StubPropertySource {
private static final String USAGE_ERROR =
"ComparisonPropertySource instances are for collection comparison " +
"use only";
"ComparisonPropertySource instances are for use with collection comparison only";
public ComparisonPropertySource(String name) {
super(name);