1 /* 2 * Copyright 2002-2009 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.core.type.filter; 18 19 import java.lang.annotation.Annotation; 20 import java.lang.annotation.Inherited; 21 22 import org.springframework.core.type.AnnotationMetadata; 23 import org.springframework.core.type.classreading.MetadataReader; 24 25 /** 26 * A simple filter which matches classes with a given annotation, 27 * checking inherited annotations as well. 28 * 29 * <p>The matching logic mirrors that of <code>Class.isAnnotationPresent()</code>. 30 * 31 * @author Mark Fisher 32 * @author Ramnivas Laddad 33 * @author Juergen Hoeller 34 * @since 2.5 35 */ 36 public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter { 37 38 private final Class<? extends Annotation> annotationType; 39 40 private final boolean considerMetaAnnotations; 41 42 43 /** 44 * Create a new AnnotationTypeFilter for the given annotation type. 45 * This filter will also match meta-annotations. To disable the 46 * meta-annotation matching, use the constructor that accepts a 47 * '<code>considerMetaAnnotations</code>' argument. The filter will 48 * not match interfaces. 49 * @param annotationType the annotation type to match 50 */ AnnotationTypeFilter(Class<? extends Annotation> annotationType)51 public AnnotationTypeFilter(Class<? extends Annotation> annotationType) { 52 this(annotationType, true); 53 } 54 55 /** 56 * Create a new AnnotationTypeFilter for the given annotation type. 57 * The filter will not match interfaces. 58 * @param annotationType the annotation type to match 59 * @param considerMetaAnnotations whether to also match on meta-annotations 60 */ AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations)61 public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) { 62 this(annotationType, considerMetaAnnotations, false); 63 } 64 65 /** 66 * Create a new {@link AnnotationTypeFilter} for the given annotation type. 67 * @param annotationType the annotation type to match 68 * @param considerMetaAnnotations whether to also match on meta-annotations 69 * @param considerInterfaces whether to also match interfaces 70 */ AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces)71 public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) { 72 super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces); 73 this.annotationType = annotationType; 74 this.considerMetaAnnotations = considerMetaAnnotations; 75 } 76 77 78 @Override matchSelf(MetadataReader metadataReader)79 protected boolean matchSelf(MetadataReader metadataReader) { 80 AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); 81 return metadata.hasAnnotation(this.annotationType.getName()) || 82 (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName())); 83 } 84 85 @Override matchSuperClass(String superClassName)86 protected Boolean matchSuperClass(String superClassName) { 87 if (Object.class.getName().equals(superClassName)) { 88 return Boolean.FALSE; 89 } 90 else if (superClassName.startsWith("java.")) { 91 try { 92 Class<?> clazz = getClass().getClassLoader().loadClass(superClassName); 93 return (clazz.getAnnotation(this.annotationType) != null); 94 } 95 catch (ClassNotFoundException ex) { 96 // Class not found - can't determine a match that way. 97 } 98 } 99 return null; 100 } 101 102 } 103