本篇记录类的读取与访问的设计与实现,如下图圈出的部分:
类的读取和访问实现
Spring使用了ASM框架对类进行读取,并且将ASM代码嵌在了Spring框架里。ASM是一个Java字节码操作和分析框架,可以对字节码进行读取,读到类的方法、注解、内部类、超类等等信息。
这里直接加了ASM的依赖,这里就包括了ClassReader、ClassVisitor、AnnotationVisitor、MethodVisitor
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.1</version>
</dependency>
类的访问者实现 - SimpleAnnotationMetadataReadingVisitor
SimpleAnnotationMetadataReadingVisitor继承了类的访问者ClassVisitor,重写了访问注解和方法的访问方法,返回了自定义的注解访问者(MergedAnnotationReadingVisitor)和方法访问者(SimpleMethodMetadataReadingVisitor)
代码实现:
package cn.zhanghongyang.core.type.classreader;
import cn.zhanghongyang.core.annotation.MergedAnnotation;
import cn.zhanghongyang.core.annotation.MergedAnnotations;
import cn.zhanghongyang.core.type.MethodMetadata;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: zhanghongyang
* @Description: 类访问者(实现类)
*/
public class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {
private String className;
private int access;
private List<MergedAnnotation> annotations = new ArrayList<>();
private List<MethodMetadata> annotatedMethod = new ArrayList<>();
private SimpleAnnotationMetadata metadata;
public SimpleAnnotationMetadataReadingVisitor() {
super(Opcodes.ASM8);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
this.className = name.replace("/", ".");
this.access = access;
}
@Override
public void visitOuterClass(String owner, String name, String descriptor) {
//外部类回调
System.out.printf("visitOuterClass回调,owner:%s, name:%s, descriptor:%s \n", owner, name, descriptor);
}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
//内部类回调
System.out.printf("visitInnerClass回调,name:%s, outerName:%s, innerName:%s, access:%d \n", name, outerName, innerName, access);
}
/**
* 访问者注解回调
* @param descriptor 注解名称 Ljava/lang/annotation/Target;
* @param visible 是否可见
* @return
*/
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
//获取类的注解,添加到annotations
return MergedAnnotationReadingVisitor.get(this.className, descriptor, visible, this.annotations::add);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
return new SimpleMethodMetadataReadingVisitor(this.className, access, name, descriptor, this.annotatedMethod::add);
}
@Override
public void visitEnd() {
//访问结束将结果封装成SimpleAnnotationMetadata
MergedAnnotations annotations = MergedAnnotations.of(this.annotations);
this.metadata = new SimpleAnnotationMetadata(this.className, this.access, null, null,
false, null, null, this.annotatedMethod.toArray(new MethodMetadata[0]), annotations);
}
public SimpleAnnotationMetadata getMetadata() {
return metadata;
}
}
合并注解访问者实现 - MergedAnnotationReadingVisitor
代码实现:
package cn.zhanghongyang.core.type.classreader;
import cn.zhanghongyang.core.annotation.AnnotationFilter;
import cn.zhanghongyang.core.annotation.MergedAnnotation;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.lang.annotation.Annotation;
import java.util.function.Consumer;
/**
* @Author: zhanghongyang
* @Description: 注解访问者(实现类)
*/
public class MergedAnnotationReadingVisitor<T extends Annotation> extends AnnotationVisitor {
/** 注解来源类全称 */
private String source;
/** 注解类型 */
private Class<T> annotationType;
/**
* 访问结束回调函数,MergedAnnotation保存了注解的信息
*/
private Consumer<MergedAnnotation> consumer;
/**
* 获取注解访问者
* @param source 注解所属类
* @param descriptor 访问回调的描述,可用获取到注解的名称
* @param visible 是否可以访问
* @param consumer 注解访问结束的回调
* @return
*/
public static AnnotationVisitor get(String source, String descriptor, boolean visible, Consumer<MergedAnnotation> consumer){
if(!visible){
return null;
}
String typeName = Type.getType(descriptor).getClassName();
//对注解进行过滤
if (AnnotationFilter.PLAIN.matches(typeName)){
return null;
}
try {
Class className = Class.forName(typeName);
return new MergedAnnotationReadingVisitor(source, className, consumer);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public MergedAnnotationReadingVisitor(String source, Class<T> annotationType, Consumer<MergedAnnotation> consumer) {
super(Opcodes.ASM8);
this.source = source;
this.annotationType = annotationType;
this.consumer = consumer;
}
@Override
public void visitEnd() {
//将注解封装成MergedAnnotation
MergedAnnotation annotation = MergedAnnotation.of(this.source, this.annotationType);
//通过回调函数带回结果
this.consumer.accept(annotation);
}
}
方法访问者实现 - SimpleMethodMetadataReadingVisitor
代码实现:
package cn.zhanghongyang.core.type.classreader;
import cn.zhanghongyang.core.type.MethodMetadata;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.util.function.Consumer;
/**
* @Author: zhanghongyang
* @Description: 方法访问者
*/
public class SimpleMethodMetadataReadingVisitor extends MethodVisitor {
/** 所属类的名称 **/
private String declaringClassName;
private int access;
private String name;
private String descriptor;
private Consumer<MethodMetadata> consumer;
public SimpleMethodMetadataReadingVisitor(String declaringClassName, int access, String name, String descriptor, Consumer<MethodMetadata> consumer) {
super(Opcodes.ASM8);
this.declaringClassName = declaringClassName;
this.access = access;
this.name = name;
this.descriptor = descriptor;
this.consumer = consumer;
}
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
return super.visitAnnotation(descriptor, visible);
}
@Override
public void visitEnd() {
String returnTypeName = Type.getReturnType(this.descriptor).getClassName();
SimpleMethodMetadata metadata = new SimpleMethodMetadata(this.name, this.access, this.declaringClassName, returnTypeName);
this.consumer.accept(metadata);
}
}