谈谈ASM字节码框架在Spring源码的应用

什么是ASM?

引用ASM官方的介绍:
ASM是一个通用的Java字节码操作和分析框架。它可以直接以二进制形式用于修改现有类或动态生成类。ASM提供了一些常见的字节码转换和分析算法,可以从中构建定制的复杂转换和代码分析工具。ASM提供了与其他Java字节码框架类似的功能,但主要关注性能。由于它的设计和实现尽可能小,速度尽可能快,因此非常适合在动态系统中使用(当然,也可以以静态方式使用,例如在编译器中)。

说白了就是我们可以通过使用ASM框架,来读取和修改.class文件。相比JDK反射技术来说,ASM提供了更方便的字节码读取方式,性能上也更加高效。

简单了解如何使用ASM框架

在ASM框架中有两个主要的类,一个是ClassVisitor,一个是ClassReader。

ClassReader接收一个输入流,读取.class文件时通过accept方法回调ClassVisitor的各类visit开头的方法;

InputStream is = new BufferedInputStream(resource.getInputStream());
ClassReader classReader = new ClassReader(is);
classReader.accept(visitor, ClassReader.SKIP_DEBUG);

通过继承ClassVisitor类,重写父类visit开头的方法

public class TClassMetadataReadingVisitor extends ClassVisitor {
   
	public TClassMetadataReadingVisitor(int api) {
   
        super(Opcodes.ASM6);
    }

	//读取类基础信息时调用的回调方法,版本、类名、父类名、接口名等
	@Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
   
        super.visit(version, access, name, signature, superName, interfaces);
    }

	//读取内部类时调用的回调方法
	@Override
    public void visitOuterClass(String owner, String name, String descriptor) {
   
        super.visitOuterClass(owner, name, descriptor);
    }
}

ClassVisitor类下的方法还有很多,这里只做简单举例说明;

Spring中ASM框架的使用

Spring中与ASM直接相关的类即为ClassMetadataReadingVisitor类;

ClassMetadataReadingVisitor,这里省略get/set方法

class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {
   

	private String className = "";

	private boolean isInterface;

	private boolean isAnnotation;

	private boolean isAbstract;

	private boolean isFinal;

	@Nullable
	private String enclosingClassName;

	private boolean independentInnerClass;

	@Nullable
	private String superClassName;

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

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


	public ClassMetadataReadingVisitor() {
   
		super(SpringAsmInfo.ASM_VERSION);
	}


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

		this.className = ClassUtils.convertResourcePathToClassName(name);
		this.isInterface = ((access & Opcodes.ACC_INTERFACE) != 0);
		this.isAnnotation = ((access & Opcodes.ACC_ANNOTATION) != 0);
		this.isAbstract = ((access & Opcodes.ACC_ABSTRACT) != 0);
		this.isFinal <
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值