custom stereotype annotations can be meta-annotated with @Service, @Controller etc as well; @Scope and @Transactional are now supported as meta-annotations on custom annotations
This commit is contained in:
@@ -137,6 +137,14 @@ public abstract class AnnotationUtils {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
if (!Annotation.class.isAssignableFrom(clazz)) {
|
||||
for (Annotation ann : clazz.getAnnotations()) {
|
||||
annotation = findAnnotation(ann.annotationType(), annotationType);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass == null || superClass.equals(Object.class)) {
|
||||
return null;
|
||||
|
||||
@@ -37,6 +37,14 @@ public interface AnnotationMetadata extends ClassMetadata {
|
||||
*/
|
||||
Set<String> getAnnotationTypes();
|
||||
|
||||
/**
|
||||
* Return the names of all meta-annotation types defined on the
|
||||
* given annotation type of the underlying class.
|
||||
* @param annotationType the meta-annotation type to look for
|
||||
* @return the meta-annotation type names
|
||||
*/
|
||||
Set<String> getMetaAnnotationTypes(String annotationType);
|
||||
|
||||
/**
|
||||
* Determine whether the underlying class has an annotation of the given
|
||||
* type defined.
|
||||
@@ -45,6 +53,14 @@ public interface AnnotationMetadata extends ClassMetadata {
|
||||
*/
|
||||
boolean hasAnnotation(String annotationType);
|
||||
|
||||
/**
|
||||
* Determine whether the underlying class has an annotation that
|
||||
* is itself annotated with the meta-annotation of the given type.
|
||||
* @param metaAnnotationType the meta-annotation type to look for
|
||||
* @return whether a matching meta-annotation is defined
|
||||
*/
|
||||
boolean hasMetaAnnotation(String metaAnnotationType);
|
||||
|
||||
/**
|
||||
* Retrieve the attributes of the annotation of the given type,
|
||||
* if any (i.e. if defined on the underlying class).
|
||||
@@ -55,22 +71,6 @@ public interface AnnotationMetadata extends ClassMetadata {
|
||||
*/
|
||||
Map<String, Object> getAnnotationAttributes(String annotationType);
|
||||
|
||||
/**
|
||||
* Return the names of all meta-annotation types defined on the
|
||||
* given annotation type of the underlying class.
|
||||
* @param annotationType the meta-annotation type to look for
|
||||
* @return the meta-annotation type names
|
||||
*/
|
||||
Set<String> getMetaAnnotationTypes(String annotationType);
|
||||
|
||||
/**
|
||||
* Determine whether the underlying class has an annotation that
|
||||
* is itself annotated with the meta-annotation of the given type.
|
||||
* @param metaAnnotationType the meta-annotation type to look for
|
||||
* @return whether a matching meta-annotation is defined
|
||||
*/
|
||||
boolean hasMetaAnnotation(String metaAnnotationType);
|
||||
|
||||
/**
|
||||
* Retrieve the method metadata for all methods that are annotated
|
||||
* with at least one annotation type.
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.core.type;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -45,7 +44,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
|
||||
|
||||
public Set<String> getAnnotationTypes() {
|
||||
Set<String> types = new HashSet<String>();
|
||||
Set<String> types = new LinkedHashSet<String>();
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
types.add(ann.annotationType().getName());
|
||||
@@ -53,6 +52,24 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
return types;
|
||||
}
|
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType().getName().equals(annotationType)) {
|
||||
Set<String> types = new LinkedHashSet<String>();
|
||||
Annotation[] metaAnns = ann.annotationType().getAnnotations();
|
||||
for (Annotation metaAnn : metaAnns) {
|
||||
types.add(metaAnn.annotationType().getName());
|
||||
for (Annotation metaMetaAnn : metaAnn.annotationType().getAnnotations()) {
|
||||
types.add(metaMetaAnn.annotationType().getName());
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasAnnotation(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
@@ -63,42 +80,37 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasMetaAnnotation(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
Annotation[] metaAnns = ann.annotationType().getAnnotations();
|
||||
for (Annotation metaAnn : metaAnns) {
|
||||
if (metaAnn.annotationType().getName().equals(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
for (Annotation metaMetaAnn : metaAnn.annotationType().getAnnotations()) {
|
||||
if (metaMetaAnn.annotationType().getName().equals(annotationType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType().getName().equals(annotationType)) {
|
||||
return AnnotationUtils.getAnnotationAttributes(ann, true);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType().getName().equals(annotationType)) {
|
||||
Set<String> types = new HashSet<String>();
|
||||
Annotation[] metaAnns = ann.annotationType().getAnnotations();
|
||||
for (Annotation meta : metaAnns) {
|
||||
types.add(meta.annotationType().getName());
|
||||
}
|
||||
return types;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasMetaAnnotation(String annotationType) {
|
||||
Annotation[] anns = getIntrospectedClass().getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
Annotation[] metaAnns = ann.annotationType().getAnnotations();
|
||||
for (Annotation meta : metaAnns) {
|
||||
if (meta.annotationType().getName().equals(annotationType)) {
|
||||
return true;
|
||||
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
|
||||
if (metaAnn.annotationType().getName().equals(annotationType)) {
|
||||
return AnnotationUtils.getAnnotationAttributes(metaAnn, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<MethodMetadata> getAnnotatedMethods() {
|
||||
|
||||
@@ -20,8 +20,8 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.asm.Type;
|
||||
import org.springframework.asm.commons.EmptyVisitor;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
/**
|
||||
* ASM visitor which looks for the annotations defined on a class or method.
|
||||
@@ -47,7 +48,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
|
||||
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
|
||||
public AnnotationAttributesReadingVisitor(
|
||||
@@ -120,6 +121,7 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor {
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
this.annotationMap.put(this.annotationType, this.attributes);
|
||||
try {
|
||||
Class<?> annotationClass = this.classLoader.loadClass(this.annotationType);
|
||||
// Check declared default values of attributes in the annotation type.
|
||||
@@ -133,10 +135,16 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor {
|
||||
}
|
||||
// Register annotations that the annotation type is annotated with.
|
||||
if (this.metaAnnotationMap != null) {
|
||||
Annotation[] metaAnnotations = annotationClass.getAnnotations();
|
||||
Set<String> metaAnnotationTypeNames = new HashSet<String>();
|
||||
for (Annotation metaAnnotation : metaAnnotations) {
|
||||
Set<String> metaAnnotationTypeNames = new LinkedHashSet<String>();
|
||||
for (Annotation metaAnnotation : annotationClass.getAnnotations()) {
|
||||
metaAnnotationTypeNames.add(metaAnnotation.annotationType().getName());
|
||||
if (!this.annotationMap.containsKey(metaAnnotation.annotationType().getName())) {
|
||||
this.annotationMap.put(metaAnnotation.annotationType().getName(),
|
||||
AnnotationUtils.getAnnotationAttributes(metaAnnotation, true));
|
||||
}
|
||||
for (Annotation metaMetaAnnotation : metaAnnotation.annotationType().getAnnotations()) {
|
||||
metaAnnotationTypeNames.add(metaMetaAnnotation.annotationType().getName());
|
||||
}
|
||||
}
|
||||
this.metaAnnotationMap.put(this.annotationType, metaAnnotationTypeNames);
|
||||
}
|
||||
@@ -144,7 +152,6 @@ final class AnnotationAttributesReadingVisitor implements AnnotationVisitor {
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Class not found - can't determine meta-annotations.
|
||||
}
|
||||
this.annotationMap.put(this.annotationType, this.attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,10 +39,12 @@ import org.springframework.core.type.MethodMetadata;
|
||||
*/
|
||||
final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata {
|
||||
|
||||
private final Map<String, Map<String, Object>> annotationMap = new LinkedHashMap<String, Map<String, Object>>();
|
||||
private final Set<String> annotationSet = new LinkedHashSet<String>();
|
||||
|
||||
private final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<String, Set<String>>();
|
||||
|
||||
private final Map<String, Map<String, Object>> attributeMap = new LinkedHashMap<String, Map<String, Object>>();
|
||||
|
||||
private final Set<MethodMetadata> methodMetadataSet = new LinkedHashSet<MethodMetadata>();
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
@@ -63,26 +65,23 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {
|
||||
String className = Type.getType(desc).getClassName();
|
||||
return new AnnotationAttributesReadingVisitor(className, this.annotationMap, this.metaAnnotationMap, this.classLoader);
|
||||
this.annotationSet.add(className);
|
||||
return new AnnotationAttributesReadingVisitor(className, this.attributeMap, this.metaAnnotationMap, this.classLoader);
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getAnnotationTypes() {
|
||||
return this.annotationMap.keySet();
|
||||
}
|
||||
|
||||
public boolean hasAnnotation(String annotationType) {
|
||||
return this.annotationMap.containsKey(annotationType);
|
||||
}
|
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) {
|
||||
return this.annotationMap.get(annotationType);
|
||||
return this.annotationSet;
|
||||
}
|
||||
|
||||
public Set<String> getMetaAnnotationTypes(String annotationType) {
|
||||
return this.metaAnnotationMap.get(annotationType);
|
||||
}
|
||||
|
||||
|
||||
public boolean hasAnnotation(String annotationType) {
|
||||
return this.annotationSet.contains(annotationType);
|
||||
}
|
||||
|
||||
public boolean hasMetaAnnotation(String metaAnnotationType) {
|
||||
Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values();
|
||||
for (Set<String> metaTypes : allMetaTypes) {
|
||||
@@ -93,6 +92,10 @@ final class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, Object> getAnnotationAttributes(String annotationType) {
|
||||
return this.attributeMap.get(annotationType);
|
||||
}
|
||||
|
||||
public Set<MethodMetadata> getAnnotatedMethods() {
|
||||
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>();
|
||||
for (MethodMetadata method : this.methodMetadataSet) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
@@ -77,8 +77,8 @@ public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter
|
||||
}
|
||||
else if (superClassName.startsWith("java.")) {
|
||||
try {
|
||||
Class clazz = getClass().getClassLoader().loadClass(superClassName);
|
||||
return Boolean.valueOf(clazz.getAnnotation(this.annotationType) != null);
|
||||
Class<?> clazz = getClass().getClassLoader().loadClass(superClassName);
|
||||
return (clazz.getAnnotation(this.annotationType) != null);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Class not found - can't determine a match that way.
|
||||
|
||||
Reference in New Issue
Block a user