001/* 002 * Copyright 2002-2020 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.classreading; 018 019import java.util.LinkedHashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.springframework.asm.AnnotationVisitor; 025import org.springframework.asm.MethodVisitor; 026import org.springframework.asm.Opcodes; 027import org.springframework.asm.SpringAsmInfo; 028import org.springframework.asm.Type; 029import org.springframework.core.annotation.AnnotationAttributes; 030import org.springframework.core.annotation.MergedAnnotations; 031import org.springframework.core.type.MethodMetadata; 032import org.springframework.lang.Nullable; 033import org.springframework.util.LinkedMultiValueMap; 034import org.springframework.util.MultiValueMap; 035 036/** 037 * ASM method visitor which looks for the annotations defined on a method, 038 * exposing them through the {@link org.springframework.core.type.MethodMetadata} 039 * interface. 040 * 041 * @author Juergen Hoeller 042 * @author Mark Pollack 043 * @author Costin Leau 044 * @author Chris Beams 045 * @author Phillip Webb 046 * @since 3.0 047 * @deprecated As of Spring Framework 5.2, this class and related classes in this 048 * package have been replaced by {@link SimpleAnnotationMetadataReadingVisitor} 049 * and related classes for internal use within the framework. 050 */ 051@Deprecated 052public class MethodMetadataReadingVisitor extends MethodVisitor implements MethodMetadata { 053 054 protected final String methodName; 055 056 protected final int access; 057 058 protected final String declaringClassName; 059 060 protected final String returnTypeName; 061 062 @Nullable 063 protected final ClassLoader classLoader; 064 065 protected final Set<MethodMetadata> methodMetadataSet; 066 067 protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<>(4); 068 069 protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<>(4); 070 071 072 public MethodMetadataReadingVisitor(String methodName, int access, String declaringClassName, 073 String returnTypeName, @Nullable ClassLoader classLoader, Set<MethodMetadata> methodMetadataSet) { 074 075 super(SpringAsmInfo.ASM_VERSION); 076 this.methodName = methodName; 077 this.access = access; 078 this.declaringClassName = declaringClassName; 079 this.returnTypeName = returnTypeName; 080 this.classLoader = classLoader; 081 this.methodMetadataSet = methodMetadataSet; 082 } 083 084 085 @Override 086 public MergedAnnotations getAnnotations() { 087 throw new UnsupportedOperationException(); 088 } 089 090 @Override 091 @Nullable 092 public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { 093 if (!visible) { 094 return null; 095 } 096 this.methodMetadataSet.add(this); 097 String className = Type.getType(desc).getClassName(); 098 return new AnnotationAttributesReadingVisitor( 099 className, this.attributesMap, this.metaAnnotationMap, this.classLoader); 100 } 101 102 103 @Override 104 public String getMethodName() { 105 return this.methodName; 106 } 107 108 @Override 109 public boolean isAbstract() { 110 return ((this.access & Opcodes.ACC_ABSTRACT) != 0); 111 } 112 113 @Override 114 public boolean isStatic() { 115 return ((this.access & Opcodes.ACC_STATIC) != 0); 116 } 117 118 @Override 119 public boolean isFinal() { 120 return ((this.access & Opcodes.ACC_FINAL) != 0); 121 } 122 123 @Override 124 public boolean isOverridable() { 125 return (!isStatic() && !isFinal() && ((this.access & Opcodes.ACC_PRIVATE) == 0)); 126 } 127 128 @Override 129 public boolean isAnnotated(String annotationName) { 130 return this.attributesMap.containsKey(annotationName); 131 } 132 133 @Override 134 @Nullable 135 public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { 136 AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( 137 this.attributesMap, this.metaAnnotationMap, annotationName); 138 if (raw == null) { 139 return null; 140 } 141 return AnnotationReadingVisitorUtils.convertClassValues( 142 "method '" + getMethodName() + "'", this.classLoader, raw, classValuesAsString); 143 } 144 145 @Override 146 @Nullable 147 public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { 148 if (!this.attributesMap.containsKey(annotationName)) { 149 return null; 150 } 151 MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<>(); 152 List<AnnotationAttributes> attributesList = this.attributesMap.get(annotationName); 153 if (attributesList != null) { 154 String annotatedElement = "method '" + getMethodName() + '\''; 155 for (AnnotationAttributes annotationAttributes : attributesList) { 156 AnnotationAttributes convertedAttributes = AnnotationReadingVisitorUtils.convertClassValues( 157 annotatedElement, this.classLoader, annotationAttributes, classValuesAsString); 158 convertedAttributes.forEach(allAttributes::add); 159 } 160 } 161 return allAttributes; 162 } 163 164 @Override 165 public String getDeclaringClassName() { 166 return this.declaringClassName; 167 } 168 169 @Override 170 public String getReturnTypeName() { 171 return this.returnTypeName; 172 } 173 174}