ASM在Spring中的应用

文章目录

  • 背景
  • IOC中注册注解BeanDefinition
  • DI中Bean的实例化
  • AOP中的cglib方式
  • MVC中参数的获取

背景

最近在非常粗糙的看spring源码,多次发现ASM在源码中的应用,简单记录下。
我的职业就是JavaAgent,对于ASM还是比较熟悉的。
ASM不仅可以在代码运行的过程中读取相应的信息,还可以修改字节码,是一个相当不错的框架。
ASM虽然很好,但是还是会添加新的逻辑,势必会消耗性能的,所以能够省去的话尽量省去,比如我们比较熟悉的@RequestParam(“name”),就可以省去ASM读取方法参数名称的操作(反射只能得到参数的类型,无法的到参数的名称)

下面看下如何在源码中找到ASM在Spring中的应用(只提供找到ASM的线索,不介绍ASM用法),嗯,只能找到部分,看的比较粗糙。

IOC中注册注解BeanDefinition

看到ClassPathScanningCandidateComponentProvider这个类中的addCandidateComponentsFromIndex()方法,找到AnnotatedGenericBeanDefinition sbd = new AnnotatedGenericBeanDefinition( metadataReader.getAnnotationMetadata());这段代码。
ASM在Spring中的应用_第1张图片
getAnnotationMetadata()方法,从字面意思理解是得到Bean的元信息。
到了SimpleMetadataReader类

final class SimpleMetadataReader implements MetadataReader {
	private final AnnotationMetadata annotationMetadata;
	@Override
	public AnnotationMetadata getAnnotationMetadata() {
		return this.annotationMetadata;
	}
}

那么返回的就是annotationMetadata 这个字段,这是一个接口,我们看其中的一个实现类AnnotationMetadataReadingVisitor
在这里插入图片描述
ASM在Spring中的应用_第2张图片
ASM在Spring中的应用_第3张图片
其实ASM简单来说就是集成ClassVisitor,然后重写里面的一系列visit***方法,通过直接修改字节码命令的方式,达到在运行期间修改字节码的技术。

好吧,不仅找到了AnnotationMetadataReadingVisitor,还找到了ClassMetadataReadingVisitor,赚大发了,在看到后缀带着Visitor基本上就柳暗花明了。
可以看到Spring中对于ASM用的还是不少的,重写了其中的visitvisitInnerClassvisitMethodvisitField

DI中Bean的实例化

SimpleInstantiationStrategy类中的instantiate方法
ASM在Spring中的应用_第4张图片
可以看到如果Bean中的方法没有被覆盖,通过反射机制调用本身的构造方法,如果有方法被覆盖了,则调用instantiateWithMethodInjection(cglib方式)方法
在这里插入图片描述
进入实现类
ASM在Spring中的应用_第5张图片
进入instantiate方法
ASM在Spring中的应用_第6张图片
进入createEnhancedSubclass方法
ASM在Spring中的应用_第7张图片
可以看到通过cglib技术生成了代理对象,cglib底层就是用的ASM开源包。

AOP中的cglib方式

众所周知,spring的aop有两种实现方式,一种是jdk的方式,一种是cglib的方式。cglib方式用的就是ASM开源包进行封装的。
首先在DefaultAopProxyFactory类中的createAopProxy方法
AOP中ASM的体现就是cglib中的Enhancer
ASM在Spring中的应用_第8张图片
然后到了CglibAopProxy类中的getProxy
ASM在Spring中的应用_第9张图片
然后依次看getCallbacks、intercept方法,进行织入,intercept方法,到了AdvisedSupport类中getInterceptorsAndDynamicInterceptionAdvice,获取调用链,从而一切变得明了。

MVC中参数的获取

MVC中参数的绑定有两种形式,一种是@RequestParam,一种是不需要注解的方法
不需要注解的方式,参数的绑定需要获得参数的name,通过反射只能得到参数的类型,所以用到了ASM
MVC就是去HandlerMapping中获取对应url的Method,然后通过反射执行。
假设看到了InvocableHandlerMethod类中的getMethodArgumentValues方法。
ASM在Spring中的应用_第10张图片
再往里面走
ASM在Spring中的应用_第11张图片
ASM在Spring中的应用_第12张图片
ASM在Spring中的应用_第13张图片
ASM在Spring中的应用_第14张图片
ASM在Spring中的应用_第15张图片
有很多的实现,我们到LocalVariableTableParameterNameDiscoverer这个类中,终于找到了这个inspectClass方法
ASM在Spring中的应用_第16张图片
进入
ASM在Spring中的应用_第17张图片
看上面的代码,那么其他的都可以忽略了,主要是ClassReader这块,通过ClassReader.accept进行织入,这个时候,我们进入ParameterNameDiscoveringVisitor这个Visitor看看它究竟做了什么

ASM在Spring中的应用_第18张图片
嗯,它重写了vistMethod方法,进入LocalVariableTableVisitor
哎一古
ASM在Spring中的应用_第19张图片
终于通过visitLocalVariable这个方法,我们能够在执行方法的时候,得到局部变量表,从而读取参数的名字,从而进行参数绑定。

西巴,终于完了。
一篇不错的文章:https://www.jianshu.com/p/f569c5705e8a

你可能感兴趣的:(#,Spring,#,JAVA,------,ASM)