Add @PropertySources and ignoreResourceNotFound
Support repeatable @PropertySource annotations in Java 8 and add @PropertySources container annotation for Java 6/7. Also add an ignoreResourceNotFound attribute to @PropertySource allowing missing property resources to be silently ignored. This commit also introduces some generally useful methods to AnnotationUtils for working with @Repeatable annotations. Issue: SPR-8371
This commit is contained in:
@@ -19,12 +19,18 @@ package org.springframework.core.annotation;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations, handling bridge methods (which the compiler
|
||||
@@ -43,6 +49,7 @@ import org.springframework.util.Assert;
|
||||
* @author Sam Brannen
|
||||
* @author Mark Fisher
|
||||
* @author Chris Beams
|
||||
* @author Phillip Webb
|
||||
* @since 2.0
|
||||
* @see java.lang.reflect.Method#getAnnotations()
|
||||
* @see java.lang.reflect.Method#getAnnotation(Class)
|
||||
@@ -117,6 +124,45 @@ public abstract class AnnotationUtils {
|
||||
return getAnnotation((AnnotatedElement) resolvedMethod, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possibly repeating {@link Annotation}s of {@code annotationType} from the
|
||||
* supplied {@link Method}. Deals with both a single direct annotation and repeating
|
||||
* annotations nested within a containing annotation.
|
||||
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
|
||||
* @param method the method to look for annotations on
|
||||
* @param containerAnnotationType the class of the container that holds the annotations
|
||||
* @param annotationType the annotation class to look for
|
||||
* @return the annotations found
|
||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
|
||||
* @since 4.0
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> getRepeatableAnnotation(Method method,
|
||||
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
|
||||
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||
return getRepeatableAnnotation((AnnotatedElement) resolvedMethod,
|
||||
containerAnnotationType, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possibly repeating {@link Annotation}s of {@code annotationType} from the
|
||||
* supplied {@link AnnotatedElement}. Deals with both a single direct annotation and
|
||||
* repeating annotations nested within a containing annotation.
|
||||
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
|
||||
* @param annotatedElement the element to look for annotations on
|
||||
* @param containerAnnotationType the class of the container that holds the annotations
|
||||
* @param annotationType the annotation class to look for
|
||||
* @return the annotations found
|
||||
* @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
|
||||
* @since 4.0
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> getRepeatableAnnotation(AnnotatedElement annotatedElement,
|
||||
Class<? extends Annotation> containerAnnotationType, Class<A> annotationType) {
|
||||
if (annotatedElement.getAnnotations().length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
return new AnnotationCollector<A>(containerAnnotationType, annotationType).getResult(annotatedElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method},
|
||||
* traversing its super methods if no annotation can be found on the given method itself.
|
||||
@@ -521,4 +567,59 @@ public abstract class AnnotationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class AnnotationCollector<A extends Annotation> {
|
||||
|
||||
|
||||
private final Class<? extends Annotation> containerAnnotationType;
|
||||
|
||||
private final Class<A> annotationType;
|
||||
|
||||
private final Set<AnnotatedElement> visited = new HashSet<AnnotatedElement>();
|
||||
|
||||
private final Set<A> result = new LinkedHashSet<A>();
|
||||
|
||||
|
||||
public AnnotationCollector(Class<? extends Annotation> containerAnnotationType,
|
||||
Class<A> annotationType) {
|
||||
this.containerAnnotationType = containerAnnotationType;
|
||||
this.annotationType = annotationType;
|
||||
}
|
||||
|
||||
|
||||
public Set<A> getResult(AnnotatedElement element) {
|
||||
process(element);
|
||||
return Collections.unmodifiableSet(this.result);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void process(AnnotatedElement annotatedElement) {
|
||||
if (this.visited.add(annotatedElement)) {
|
||||
for (Annotation annotation : annotatedElement.getAnnotations()) {
|
||||
if (ObjectUtils.nullSafeEquals(this.annotationType, annotation.annotationType())) {
|
||||
this.result.add((A) annotation);
|
||||
}
|
||||
else if (ObjectUtils.nullSafeEquals(this.containerAnnotationType, annotation.annotationType())) {
|
||||
result.addAll(Arrays.asList(getValue(annotation)));
|
||||
}
|
||||
else {
|
||||
process(annotation.annotationType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private A[] getValue(Annotation annotation) {
|
||||
try {
|
||||
Method method = annotation.annotationType().getDeclaredMethod("value");
|
||||
return (A[]) method.invoke(annotation);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable to read value from repeating annotation container "
|
||||
+ this.containerAnnotationType.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user