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.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021import java.util.Map; 022 023import org.springframework.core.annotation.AnnotatedElementUtils; 024import org.springframework.core.annotation.MergedAnnotations; 025import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; 026import org.springframework.core.annotation.RepeatableContainers; 027import org.springframework.lang.Nullable; 028import org.springframework.util.Assert; 029import org.springframework.util.MultiValueMap; 030 031/** 032 * {@link MethodMetadata} implementation that uses standard reflection 033 * to introspect a given {@code Method}. 034 * 035 * @author Juergen Hoeller 036 * @author Mark Pollack 037 * @author Chris Beams 038 * @author Phillip Webb 039 * @since 3.0 040 */ 041public class StandardMethodMetadata implements MethodMetadata { 042 043 private final Method introspectedMethod; 044 045 private final boolean nestedAnnotationsAsMap; 046 047 private final MergedAnnotations mergedAnnotations; 048 049 050 /** 051 * Create a new StandardMethodMetadata wrapper for the given Method. 052 * @param introspectedMethod the Method to introspect 053 * @deprecated since 5.2 in favor of obtaining instances via {@link AnnotationMetadata} 054 */ 055 @Deprecated 056 public StandardMethodMetadata(Method introspectedMethod) { 057 this(introspectedMethod, false); 058 } 059 060 /** 061 * Create a new StandardMethodMetadata wrapper for the given Method, 062 * providing the option to return any nested annotations or annotation arrays in the 063 * form of {@link org.springframework.core.annotation.AnnotationAttributes} instead 064 * of actual {@link java.lang.annotation.Annotation} instances. 065 * @param introspectedMethod the Method to introspect 066 * @param nestedAnnotationsAsMap return nested annotations and annotation arrays as 067 * {@link org.springframework.core.annotation.AnnotationAttributes} for compatibility 068 * with ASM-based {@link AnnotationMetadata} implementations 069 * @since 3.1.1 070 * @deprecated since 5.2 in favor of obtaining instances via {@link AnnotationMetadata} 071 */ 072 @Deprecated 073 public StandardMethodMetadata(Method introspectedMethod, boolean nestedAnnotationsAsMap) { 074 Assert.notNull(introspectedMethod, "Method must not be null"); 075 this.introspectedMethod = introspectedMethod; 076 this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; 077 this.mergedAnnotations = MergedAnnotations.from( 078 introspectedMethod, SearchStrategy.DIRECT, RepeatableContainers.none()); 079 } 080 081 082 @Override 083 public MergedAnnotations getAnnotations() { 084 return this.mergedAnnotations; 085 } 086 087 /** 088 * Return the underlying Method. 089 */ 090 public final Method getIntrospectedMethod() { 091 return this.introspectedMethod; 092 } 093 094 @Override 095 public String getMethodName() { 096 return this.introspectedMethod.getName(); 097 } 098 099 @Override 100 public String getDeclaringClassName() { 101 return this.introspectedMethod.getDeclaringClass().getName(); 102 } 103 104 @Override 105 public String getReturnTypeName() { 106 return this.introspectedMethod.getReturnType().getName(); 107 } 108 109 @Override 110 public boolean isAbstract() { 111 return Modifier.isAbstract(this.introspectedMethod.getModifiers()); 112 } 113 114 @Override 115 public boolean isStatic() { 116 return Modifier.isStatic(this.introspectedMethod.getModifiers()); 117 } 118 119 @Override 120 public boolean isFinal() { 121 return Modifier.isFinal(this.introspectedMethod.getModifiers()); 122 } 123 124 @Override 125 public boolean isOverridable() { 126 return !isStatic() && !isFinal() && !isPrivate(); 127 } 128 129 private boolean isPrivate() { 130 return Modifier.isPrivate(this.introspectedMethod.getModifiers()); 131 } 132 133 @Override 134 @Nullable 135 public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) { 136 if (this.nestedAnnotationsAsMap) { 137 return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString); 138 } 139 return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod, 140 annotationName, classValuesAsString, false); 141 } 142 143 @Override 144 @Nullable 145 public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { 146 if (this.nestedAnnotationsAsMap) { 147 return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString); 148 } 149 return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod, 150 annotationName, classValuesAsString, false); 151 } 152 153}