尴尬,看看啥时候给它赋值的:
@Override public AnnotationVisitor visitAnnotation(final String desc, boolean visible) { String className = Type.getType(desc).getClassName(); this.annotationSet.add(className); return new AnnotationAttributesReadingVisitor(className, this.attributeMap, this.metaAnnotationMap, this.classLoader, this.logger); }方法名字,见名猜意思,:visit注解,可能还使用了visitor设计模式,但是这个方法又是什么时候被调用的呢
asm简介简单介绍下asm框架,官网:
https://asm.ow2.io/
https://asm.ow2.io/asm4-guide.pdf
官网说明如下:
ASM is an all purpose Java bytecode manipulation and analysis framework. It can be used to modify existing classes or to dynamically generate classes, directly in binary form. ASM provides some common bytecode transformations and analysis algorithms from which custom complex transformations and code analysis tools can be built. ASM offers similar functionality as other Java bytecode frameworks, but is focused on performance. Because it was designed and implemented to be as small and as fast as possible, it is well suited for use in dynamic systems (but can of course be used in a static way too, e.g. in compilers).
ASM is used in many projects, including:
the OpenJDK, to generate the lambda call sites, and also in the compiler,
the Groovy compiler and the Kotlin compiler,
Cobertura and Jacoco, to instrument classes in order to measure code coverage,
CGLIB, to dynamically generate proxy classes (which are used in other projects such as Mockito and EasyMock),
Gradle, to generate some classes at runtime.
简单来说,就是:
asm是一个字节码操作和分析的框架,能够用来修改已存在的class,或者动态生成class,直接以二进制的形式。ASM提供一些通用的字节码转换和分析算法,通过这些算法,可以构建复杂的字节码转换和代码分析工具。ASM提供和其他字节码框架类似的功能,但是其专注于性能。因为它被设计和实现为,尽可能的小,尽可能的快。
ASM被用在很多项目,包括:
OpenJDK,生成lambda调用;
Groovy和Kotlin的编译器
Cobertura和Jacoco,通过探针,检测代码覆盖率
CGLIB,动态生成代理类,也用在Mockito和EasyMock中
Gradle,运行时动态生成类
这里补充一句,ASM为啥说它专注于性能,因为,要动态生成类、动态进行字节码转换,如果性能太差的话,还有人用吗? 为啥要足够小,足够小因为它也希望自己用在一些内存受限的环境中。
查看了asm的官方文档,发现一个有趣的知识,asm这个名字,来源于c语言里面的__asm__关键字,这个关键字可以在c语言里用汇编来实现某些功能。
另外,其官方文档里提到,解析class文件的过程,有两种模型,一种是基于事件的,一种是基于对象的,可以类比xml解析中的sax和dom模型,sax就是基于事件的,同样也是和asm一样,使用visitor模式。
visitor模式呢,我的简单理解,就是主程序定义好了一切流程,比如我会按照顺序来访问一个class,先是class name,就去调用visitor的对应方法,此时,visitor可以做些处理;我访问到field时,也会调用visitor的对应方法...以此类推。
asm怎么读取class针对每个class,asm是把它当作一个Resource,其大概的解析步骤如下:
import org.springframework.asm.ClassReader; import org.springframework.core.NestedIOException; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.ClassMetadata; SimpleMetadataReader(Resource resource, ClassLoader classLoader, MetadataReaderLog logger) throws IOException { // 1. InputStream is = new BufferedInputStream(resource.getInputStream()); ClassReader classReader = new ClassReader(is); // 2. AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader, logger); // 3. classReader.accept(visitor, ClassReader.SKIP_DEBUG); this.annotationMetadata = visitor; // (since AnnotationMetadataReader extends ClassMetadataReadingVisitor) this.classMetadata = visitor; this.resource = resource; }各讲解点:
读取class resource为输入流,作为构造器参数,new一个asm的ClassReader出来;