org.springframework.asm 使用

git地址:
https://github.com/lixiao853771701/springBootAsmDemo

参考的spring加载类的代码

spring的类 SimpleMetadataReader中
构造方法
SimpleMetadataReader(Resource resource, @Nullable ClassLoader classLoader) throws IOException {
		SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(classLoader);
		getClassReader(resource).accept(visitor, PARSING_OPTIONS);
		this.resource = resource;
		this.annotationMetadata = visitor.getMetadata();
	}
	其中这一行 getClassReader(resource).accept(visitor, PARSING_OPTIONS); 就是利用了ASM技术读取
	getClassReader(resource)点进去
	private static ClassReader getClassReader(Resource resource) throws IOException {
		try (InputStream is = resource.getInputStream()) {
			try {
				return new ClassReader(is);
			}
			catch (IllegalArgumentException ex) {
				throw new org.springframework.core.NestedIOException("ASM ClassReader failed to parse class file - " +
						"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
			}
		}
	}

以下是扒下来的代码:
MergedAnnotationReadingVisitor

public class MergedAnnotationReadingVisitor<A extends Annotation> extends AnnotationVisitor {

    @Nullable
    private final ClassLoader classLoader;

    @Nullable
    private final Object source;

    private final Class<A> annotationType;

    private final Consumer<MergedAnnotation<A>> consumer;

    private final Map<String, Object> attributes = new LinkedHashMap<>(4);


    public MergedAnnotationReadingVisitor(@Nullable ClassLoader classLoader, @Nullable Object source,
                                          Class<A> annotationType, Consumer<MergedAnnotation<A>> consumer) {

        super(SpringAsmInfo.ASM_VERSION);
        this.classLoader = classLoader;
        this.source = source;
        this.annotationType = annotationType;
        this.consumer = consumer;
    }


    @Override
    public void visit(String name, Object value) {
        if (value instanceof Type) {
            value = ((Type) value).getClassName();
        }
        this.attributes.put(name, value);
    }

    @Override
    public void visitEnum(String name, String descriptor, String value) {
        visitEnum(descriptor, value, enumValue -> this.attributes.put(name, enumValue));
    }

    @Override
    @Nullable
    public AnnotationVisitor visitAnnotation(String name, String descriptor) {
        return visitAnnotation(descriptor, annotation -> this.attributes.put(name, annotation));
    }

    @Override
    public AnnotationVisitor visitArray(String name) {
        return new MergedAnnotationReadingVisitor.ArrayVisitor(value -> this.attributes.put(name, value));
    }

    @Override
    public void visitEnd() {
        MergedAnnotation<A> annotation = MergedAnnotation.of(
                this.classLoader, this.source, this.annotationType, this.attributes);
        this.consumer.accept(annotation);
    }

    @SuppressWarnings("unchecked")
    public <E extends Enum<E>> void visitEnum(String descriptor, String value, Consumer<E> consumer) {
        String className = Type.getType(descriptor).getClassName();
        Class<E> type = (Class<E>) ClassUtils.resolveClassName(className, this.classLoader);
        consumer.accept(Enum.valueOf(type, value));
    }

    @SuppressWarnings("unchecked")
    @Nullable
    private <T extends Annotation> AnnotationVisitor visitAnnotation(
            String descriptor, Consumer<MergedAnnotation<T>> consumer) {

        String className = Type.getType(descriptor).getClassName();
        if (AnnotationFilter.PLAIN.matches(className)) {
            return null;
        }
        Class<T> type = (Class<T>) ClassUtils.resolveClassName(className, this.classLoader);
        return new MergedAnnotationReadingVisitor<>(this.classLoader, this.source, type, consumer);
    }

    @SuppressWarnings("unchecked")
    @Nullable
    static <A extends Annotation> AnnotationVisitor get(@Nullable ClassLoader classLoader,
                                                        @Nullable Object source, String descriptor, boolean visible,
                                                        Consumer<MergedAnnotation<A>> consumer) {

        if (!visible) {
            return null;
        }

        String typeName = Type.getType(descriptor).getClassName();
        if (AnnotationFilter.PLAIN.matches(typeName)) {
            return null;
        }

        try {
            Class<A> annotationType = (Class<A>) ClassUtils.forName(typeName, classLoader);
            return new MergedAnnotationReadingVisitor<>(classLoader, source, annotationType, consumer);
        }
        catch (ClassNotFoundException | LinkageError ex) {
            return null;
        }
    }


    /**
     * {@link AnnotationVisitor} to deal with array attributes.
     */
    private class ArrayVisitor extends AnnotationVisitor {

        private final List<Object> elements = new ArrayList<>();

        private final Consumer<Object[]> consumer;

        ArrayVisitor(Consumer<Object[]> consumer) {
            super(SpringAsmInfo.ASM_VERSION);
            this.consumer = consumer;
        }

        @Override
        public void visit(String name, Object value) {
            if (value instanceof Type) {
                value = ((Type) value).getClassName();
            }
            this.elements.add(value);
        }

        @Override
        public void visitEnum(String name, String descriptor, String value) {
            MergedAnnotationReadingVisitor.this.visitEnum(descriptor, value, this.elements::add);
        }

        @Override
        @Nullable
        public AnnotationVisitor visitAnnotation(String name, String descriptor) {
            return MergedAnnotationReadingVisitor.this.visitAnnotation(descriptor, this.elements::add);
        }

        @Override
        public void visitEnd() {
            Class<?> componentType = getComponentType();
            Object[] array = (Object[]) Array.newInstance(componentType, this.elements.size());
            this.consumer.accept(this.elements.toArray(array));
        }

        private Class<?> getComponentType() {
            if (this.elements.isEmpty()) {
                return Object.class;
            }
            Object firstElement = this.elements.get(0);
            if (firstElement instanceof Enum) {
                return ((Enum<?>) firstElement).getDeclaringClass();
            }
            return firstElement.getClass();
        }
    }

}

SimpleAnnotationMetadata

public class SimpleAnnotationMetadata implements AnnotationMetadata {

    private final String className;

    private final int access;

    @Nullable
    private final String enclosingClassName;

    @Nullable
    private final String superClassName;

    private final boolean independentInnerClass;

    private final String[] interfaceNames;

    private final String[] memberClassNames;

    private final MethodMetadata[] annotatedMethods;

    private final MergedAnnotations annotations;

    @Nullable
    private Set<String> annotationTypes;


    SimpleAnnotationMetadata(String className, int access, @Nullable String enclosingClassName,
                             @Nullable String superClassName, boolean independentInnerClass, String[] interfaceNames,
                             String[] memberClassNames, MethodMetadata[] annotatedMethods, MergedAnnotations annotations) {

        this.className = className;
        this.access = access;
        this.enclosingClassName = enclosingClassName;
        this.superClassName = superClassName;
        this.independentInnerClass = independentInnerClass;
        this.interfaceNames = interfaceNames;
        this.memberClassNames = memberClassNames;
        this.annotatedMethods = annotatedMethods;
        this.annotations = annotations;
    }

    @Override
    public String getClassName() {
        return this.className;
    }

    @Override
    public boolean isInterface() {
        return (this.access & Opcodes.ACC_INTERFACE) != 0;
    }

    @Override
    public boolean isAnnotation() {
        return (this.access & Opcodes.ACC_ANNOTATION) != 0;
    }

    @Override
    public boolean isAbstract() {
        return (this.access & Opcodes.ACC_ABSTRACT) != 0;
    }

    @Override
    public boolean isFinal() {
        return (this.access & Opcodes.ACC_FINAL) != 0;
    }

    @Override
    public boolean isIndependent() {
        return (this.enclosingClassName == null || this.independentInnerClass);
    }

    @Override
    @Nullable
    public String getEnclosingClassName() {
        return this.enclosingClassName;
    }

    @Override
    @Nullable
    public String getSuperClassName() {
        return this.superClassName;
    }

    @Override
    public String[] getInterfaceNames() {
        return this.interfaceNames.clone();
    }

    @Override
    public String[] getMemberClassNames() {
        return this.memberClassNames.clone();
    }

    @Override
    public MergedAnnotations getAnnotations() {
        return this.annotations;
    }

    @Override
    public Set<String> getAnnotationTypes() {
        Set<String> annotationTypes = this.annotationTypes;
        if (annotationTypes == null) {
            annotationTypes = Collections.unmodifiableSet(
                    AnnotationMetadata.super.getAnnotationTypes());
            this.annotationTypes = annotationTypes;
        }
        return annotationTypes;
    }

    @Override
    public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
        Set<MethodMetadata> annotatedMethods = null;
        for (MethodMetadata annotatedMethod : this.annotatedMethods) {
            if (annotatedMethod.isAnnotated(annotationName)) {
                if (annotatedMethods == null) {
                    annotatedMethods = new LinkedHashSet<>(4);
                }
                annotatedMethods.add(annotatedMethod);
            }
        }
        return (annotatedMethods != null ? annotatedMethods : Collections.emptySet());
    }


    @Override
    public boolean equals(@Nullable Object obj) {
//        return ((this == obj) || ((obj instanceof org.springframework.core.type.classreading.SimpleAnnotationMetadata) &&
//                this.className.equals(((org.springframework.core.type.classreading.SimpleAnnotationMetadata) obj).className)));
        return false;
    }

    @Override
    public int hashCode() {
        return this.className.hashCode();
    }

    @Override
    public String toString() {
        return this.className;
    }

}

SimpleAnnotationMetadataReadingVisitor

public class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {

    @Nullable
    private final ClassLoader classLoader;

    private String className = "";

    private int access;

    @Nullable
    private String superClassName;

    private String[] interfaceNames = new String[0];

    @Nullable
    private String enclosingClassName;

    private boolean independentInnerClass;

    private Set<String> memberClassNames = new LinkedHashSet<>(4);

    private List<MergedAnnotation<?>> annotations = new ArrayList<>();

    private List<SimpleMethodMetadata> annotatedMethods = new ArrayList<>();

    @Nullable
    private SimpleAnnotationMetadata metadata;

    @Nullable
    private Source source;


    SimpleAnnotationMetadataReadingVisitor(@Nullable ClassLoader classLoader) {
        super(SpringAsmInfo.ASM_VERSION);
        this.classLoader = classLoader;
    }


    @Override
    public void visit(int version, int access, String name, String signature,
                      @Nullable String supername, String[] interfaces) {

        this.className = toClassName(name);
        this.access = access;
        if (supername != null && !isInterface(access)) {
            this.superClassName = toClassName(supername);
        }
        this.interfaceNames = new String[interfaces.length];
        for (int i = 0; i < interfaces.length; i++) {
            this.interfaceNames[i] = toClassName(interfaces[i]);
        }
    }

    @Override
    public void visitOuterClass(String owner, String name, String desc) {
        this.enclosingClassName = toClassName(owner);
    }

    @Override
    public void visitInnerClass(String name, @Nullable String outerName, String innerName, int access) {
        if (outerName != null) {
            String className = toClassName(name);
            String outerClassName = toClassName(outerName);
            if (this.className.equals(className)) {
                this.enclosingClassName = outerClassName;
                this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);
            }
            else if (this.className.equals(outerClassName)) {
                this.memberClassNames.add(className);
            }
        }
    }

    @Override
    @Nullable
    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
        return MergedAnnotationReadingVisitor.get(this.classLoader, getSource(),
                descriptor, visible, this.annotations::add);
    }

    @Override
    @Nullable
    public MethodVisitor visitMethod(
            int access, String name, String descriptor, String signature, String[] exceptions) {

        // Skip bridge methods - we're only interested in original
        // annotation-defining user methods. On JDK 8, we'd otherwise run into
        // double detection of the same annotated method...
        if (isBridge(access)) {
            return null;
        }
        return new SimpleMethodMetadataReadingVisitor(this.classLoader, this.className,
                access, name, descriptor, this.annotatedMethods::add);
    }

    @Override
    public void visitEnd() {
        String[] memberClassNames = StringUtils.toStringArray(this.memberClassNames);
        MethodMetadata[] annotatedMethods = this.annotatedMethods.toArray(new MethodMetadata[0]);
        MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
        this.metadata = new SimpleAnnotationMetadata(this.className, this.access,
                this.enclosingClassName, this.superClassName, this.independentInnerClass,
                this.interfaceNames, memberClassNames, annotatedMethods, annotations);
    }

    public SimpleAnnotationMetadata getMetadata() {
        Assert.state(this.metadata != null, "AnnotationMetadata not initialized");
        return this.metadata;
    }

    private SimpleAnnotationMetadataReadingVisitor.Source getSource() {
        SimpleAnnotationMetadataReadingVisitor.Source source = this.source;
        if (source == null) {
            source = new SimpleAnnotationMetadataReadingVisitor.Source(this.className);
            this.source = source;
        }
        return source;
    }

    private String toClassName(String name) {
        return ClassUtils.convertResourcePathToClassName(name);
    }

    private boolean isBridge(int access) {
        return (access & Opcodes.ACC_BRIDGE) != 0;
    }

    private boolean isInterface(int access) {
        return (access & Opcodes.ACC_INTERFACE) != 0;
    }

    /**
     * {@link MergedAnnotation} source.
     */
    private static final class Source {

        private final String className;

        Source(String className) {
            this.className = className;
        }

        @Override
        public int hashCode() {
            return this.className.hashCode();
        }

        @Override
        public boolean equals(@Nullable Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null || getClass() != obj.getClass()) {
                return false;
            }
            return this.className.equals(((SimpleAnnotationMetadataReadingVisitor.Source) obj).className);
        }

        @Override
        public String toString() {
            return this.className;
        }

    }

}

SimpleMethodMetadata

public class SimpleMethodMetadata implements MethodMetadata {

    private final String methodName;

    private final int access;

    private final String declaringClassName;

    private final String returnTypeName;

    // The source implements equals(), hashCode(), and toString() for the underlying method.
    private final Object source;

    private final MergedAnnotations annotations;


    SimpleMethodMetadata(String methodName, int access, String declaringClassName,
                         String returnTypeName, Object source, MergedAnnotations annotations) {

        this.methodName = methodName;
        this.access = access;
        this.declaringClassName = declaringClassName;
        this.returnTypeName = returnTypeName;
        this.source = source;
        this.annotations = annotations;
    }


    @Override
    public String getMethodName() {
        return this.methodName;
    }

    @Override
    public String getDeclaringClassName() {
        return this.declaringClassName;
    }

    @Override
    public String getReturnTypeName() {
        return this.returnTypeName;
    }

    @Override
    public boolean isAbstract() {
        return (this.access & Opcodes.ACC_ABSTRACT) != 0;
    }

    @Override
    public boolean isStatic() {
        return (this.access & Opcodes.ACC_STATIC) != 0;
    }

    @Override
    public boolean isFinal() {
        return (this.access & Opcodes.ACC_FINAL) != 0;
    }

    @Override
    public boolean isOverridable() {
        return !isStatic() && !isFinal() && !isPrivate();
    }

    private boolean isPrivate() {
        return (this.access & Opcodes.ACC_PRIVATE) != 0;
    }

    @Override
    public MergedAnnotations getAnnotations() {
        return this.annotations;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        return ((this == obj) || ((obj instanceof SimpleMethodMetadata) &&
                this.source.equals(((SimpleMethodMetadata) obj).source)));
    }

    @Override
    public int hashCode() {
        return this.source.hashCode();
    }

    @Override
    public String toString() {
        return this.source.toString();
    }

}

SimpleMethodMetadataReadingVisitor

public class SimpleMethodMetadataReadingVisitor extends MethodVisitor {

    @Nullable
    private final ClassLoader classLoader;

    private final String declaringClassName;

    private final int access;

    private final String methodName;

    private final String descriptor;

    private final List<MergedAnnotation<?>> annotations = new ArrayList<>(4);

    private final Consumer<SimpleMethodMetadata> consumer;

    @Nullable
    private SimpleMethodMetadataReadingVisitor.Source source;


    SimpleMethodMetadataReadingVisitor(@Nullable ClassLoader classLoader, String declaringClassName,
                                       int access, String methodName, String descriptor, Consumer<SimpleMethodMetadata> consumer) {

        super(SpringAsmInfo.ASM_VERSION);
        this.classLoader = classLoader;
        this.declaringClassName = declaringClassName;
        this.access = access;
        this.methodName = methodName;
        this.descriptor = descriptor;
        this.consumer = consumer;
    }


    @Override
    @Nullable
    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
        return MergedAnnotationReadingVisitor.get(this.classLoader, getSource(),
                descriptor, visible, this.annotations::add);
    }

    @Override
    public void visitEnd() {
        if (!this.annotations.isEmpty()) {
            String returnTypeName = Type.getReturnType(this.descriptor).getClassName();
            MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
            SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.methodName, this.access,
                    this.declaringClassName, returnTypeName, getSource(), annotations);
            this.consumer.accept(metadata);
        }
    }

    private Object getSource() {
        SimpleMethodMetadataReadingVisitor.Source source = this.source;
        if (source == null) {
            source = new SimpleMethodMetadataReadingVisitor.Source(this.declaringClassName, this.methodName, this.descriptor);
            this.source = source;
        }
        return source;
    }


    /**
     * {@link MergedAnnotation} source.
     */
    static final class Source {

        private final String declaringClassName;

        private final String methodName;

        private final String descriptor;

        @Nullable
        private String toStringValue;

        Source(String declaringClassName, String methodName, String descriptor) {
            this.declaringClassName = declaringClassName;
            this.methodName = methodName;
            this.descriptor = descriptor;
        }

        @Override
        public int hashCode() {
            int result = 1;
            result = 31 * result + this.declaringClassName.hashCode();
            result = 31 * result + this.methodName.hashCode();
            result = 31 * result + this.descriptor.hashCode();
            return result;
        }

        @Override
        public boolean equals(@Nullable Object other) {
            if (this == other) {
                return true;
            }
            if (other == null || getClass() != other.getClass()) {
                return false;
            }
            SimpleMethodMetadataReadingVisitor.Source otherSource = (SimpleMethodMetadataReadingVisitor.Source) other;
            return (this.declaringClassName.equals(otherSource.declaringClassName) &&
                    this.methodName.equals(otherSource.methodName) && this.descriptor.equals(otherSource.descriptor));
        }

        @Override
        public String toString() {
            String value = this.toStringValue;
            if (value == null) {
                StringBuilder builder = new StringBuilder();
                builder.append(this.declaringClassName);
                builder.append('.');
                builder.append(this.methodName);
                Type[] argumentTypes = Type.getArgumentTypes(this.descriptor);
                builder.append('(');
                for (int i = 0; i < argumentTypes.length; i++) {
                    if (i != 0) {
                        builder.append(',');
                    }
                    builder.append(argumentTypes[i].getClassName());
                }
                builder.append(')');
                value = builder.toString();
                this.toStringValue = value;
            }
            return value;
        }
    }

}

Test

public class Test {

    public static void main(String[] args) throws Exception {
        InputStream resourceAsStream = ClassLoader.getSystemClassLoader().getResourceAsStream("com\\xx\\xxx\\Xxxx.class");
        ClassReader classReader = new ClassReader(resourceAsStream);
        SimpleAnnotationMetadataReadingVisitor visitor = new SimpleAnnotationMetadataReadingVisitor(ClassLoader.getSystemClassLoader());
        classReader.accept(visitor, 2);
        System.out.println();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值