001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.core.type; 018 019import java.util.Collections; 020import java.util.LinkedHashSet; 021import java.util.Set; 022import java.util.stream.Collectors; 023 024import org.springframework.core.annotation.MergedAnnotation; 025import org.springframework.core.annotation.MergedAnnotations; 026import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; 027 028/** 029 * Interface that defines abstract access to the annotations of a specific 030 * class, in a form that does not require that class to be loaded yet. 031 * 032 * @author Juergen Hoeller 033 * @author Mark Fisher 034 * @author Phillip Webb 035 * @author Sam Brannen 036 * @since 2.5 037 * @see StandardAnnotationMetadata 038 * @see org.springframework.core.type.classreading.MetadataReader#getAnnotationMetadata() 039 * @see AnnotatedTypeMetadata 040 */ 041public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { 042 043 /** 044 * Get the fully qualified class names of all annotation types that 045 * are <em>present</em> on the underlying class. 046 * @return the annotation type names 047 */ 048 default Set<String> getAnnotationTypes() { 049 return getAnnotations().stream() 050 .filter(MergedAnnotation::isDirectlyPresent) 051 .map(annotation -> annotation.getType().getName()) 052 .collect(Collectors.toCollection(LinkedHashSet::new)); 053 } 054 055 /** 056 * Get the fully qualified class names of all meta-annotation types that 057 * are <em>present</em> on the given annotation type on the underlying class. 058 * @param annotationName the fully qualified class name of the meta-annotation 059 * type to look for 060 * @return the meta-annotation type names, or an empty set if none found 061 */ 062 default Set<String> getMetaAnnotationTypes(String annotationName) { 063 MergedAnnotation<?> annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent); 064 if (!annotation.isPresent()) { 065 return Collections.emptySet(); 066 } 067 return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream() 068 .map(mergedAnnotation -> mergedAnnotation.getType().getName()) 069 .collect(Collectors.toCollection(LinkedHashSet::new)); 070 } 071 072 /** 073 * Determine whether an annotation of the given type is <em>present</em> on 074 * the underlying class. 075 * @param annotationName the fully qualified class name of the annotation 076 * type to look for 077 * @return {@code true} if a matching annotation is present 078 */ 079 default boolean hasAnnotation(String annotationName) { 080 return getAnnotations().isDirectlyPresent(annotationName); 081 } 082 083 /** 084 * Determine whether the underlying class has an annotation that is itself 085 * annotated with the meta-annotation of the given type. 086 * @param metaAnnotationName the fully qualified class name of the 087 * meta-annotation type to look for 088 * @return {@code true} if a matching meta-annotation is present 089 */ 090 default boolean hasMetaAnnotation(String metaAnnotationName) { 091 return getAnnotations().get(metaAnnotationName, 092 MergedAnnotation::isMetaPresent).isPresent(); 093 } 094 095 /** 096 * Determine whether the underlying class has any methods that are 097 * annotated (or meta-annotated) with the given annotation type. 098 * @param annotationName the fully qualified class name of the annotation 099 * type to look for 100 */ 101 default boolean hasAnnotatedMethods(String annotationName) { 102 return !getAnnotatedMethods(annotationName).isEmpty(); 103 } 104 105 /** 106 * Retrieve the method metadata for all methods that are annotated 107 * (or meta-annotated) with the given annotation type. 108 * <p>For any returned method, {@link MethodMetadata#isAnnotated} will 109 * return {@code true} for the given annotation type. 110 * @param annotationName the fully qualified class name of the annotation 111 * type to look for 112 * @return a set of {@link MethodMetadata} for methods that have a matching 113 * annotation. The return value will be an empty set if no methods match 114 * the annotation type. 115 */ 116 Set<MethodMetadata> getAnnotatedMethods(String annotationName); 117 118 119 /** 120 * Factory method to create a new {@link AnnotationMetadata} instance 121 * for the given class using standard reflection. 122 * @param type the class to introspect 123 * @return a new {@link AnnotationMetadata} instance 124 * @since 5.2 125 */ 126 static AnnotationMetadata introspect(Class<?> type) { 127 return StandardAnnotationMetadata.from(type); 128 } 129 130}