曹工说Spring Boot源码(24)-- Spring注解扫描的瑞士军刀,asm技术实战(上)

曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享

曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解

曹工说Spring Boot源码(3)-- 手动注册Bean Definition不比游戏好玩吗,我们来试一下

曹工说Spring Boot源码(4)-- 我是怎么自定义ApplicationContext,从json文件读取bean definition的?

曹工说Spring Boot源码(5)-- 怎么从properties文件读取bean

曹工说Spring Boot源码(6)-- Spring怎么从xml文件里解析bean的

曹工说Spring Boot源码(7)-- Spring解析xml文件,到底从中得到了什么(上)

曹工说Spring Boot源码(8)-- Spring解析xml文件,到底从中得到了什么(util命名空间)

曹工说Spring Boot源码(9)-- Spring解析xml文件,到底从中得到了什么(context命名空间上)

曹工说Spring Boot源码(10)-- Spring解析xml文件,到底从中得到了什么(context:annotation-config 解析)

曹工说Spring Boot源码(11)-- context:component-scan,你真的会用吗(这次来说说它的奇技淫巧)

曹工说Spring Boot源码(12)-- Spring解析xml文件,到底从中得到了什么(context:component-scan完整解析)

曹工说Spring Boot源码(13)-- AspectJ的运行时织入(Load-Time-Weaving),基本内容是讲清楚了(附源码)

曹工说Spring Boot源码(14)-- AspectJ的Load-Time-Weaving的两种实现方式细细讲解,以及怎么和Spring Instrumentation集成

曹工说Spring Boot源码(15)-- Spring从xml文件里到底得到了什么(context:load-time-weaver 完整解析)

曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析【上】)

曹工说Spring Boot源码(17)-- Spring从xml文件里到底得到了什么(aop:config完整解析【中】)

曹工说Spring Boot源码(18)-- Spring AOP源码分析三部曲,终于快讲完了 (aop:config完整解析【下】)

曹工说Spring Boot源码(19)-- Spring 带给我们的工具利器,创建代理不用愁(ProxyFactory)

曹工说Spring Boot源码(20)-- 码网恢恢,疏而不漏,如何记录Spring RedisTemplate每次操作日志

曹工说Spring Boot源码(21)-- 为了让大家理解Spring Aop利器ProxyFactory,我已经拼了

曹工说Spring Boot源码(22)-- 你说我Spring Aop依赖AspectJ,我依赖它什么了

曹工说Spring Boot源码(23)-- ASM又立功了,Spring原来是这么递归获取注解的元注解的

工程代码地址 思维导图地址

工程结构图:

曹工说Spring Boot源码(24)-- Spring注解扫描的瑞士军刀,asm技术实战(上)

概要

上一篇,我们讲了spring是怎么获取class上的注解,以及注解的元注解的。在注解大行其道的今天,理解这些相对底层一点的知识,是绝对有必要的。另外,在上一讲中,我们提到了,spring其实最终也是利用ASM去读取注解的,其中,还使用了访问者设计模式。

访问者设计模式有效地分离了对数据的访问和和对数据的操作,因为class结构是很固定的,所以,visitor模式就尤其适合。在访问到特定数据时,就回调应用注册的回调方法。ASM基本上就是在visitor这个设计模式的基础上建立起来的。

今天,我们的主题有两个,1是简单地了解下ASM,2是投入实战,看看要怎么去利用ASM + java的Intrumentation机制,来在java启动时,就去修改class,实现简单的aop功能。

本篇覆盖第一个主题,下一个主题留带下一篇(demo已经ok了)。

ASM的核心之读取功能

我们目的是读取以下测试类上的注解和所有的方法的名称。

以下代码demo见:https://gitee.com/ckl111/all-simple-demo-in-work/tree/master/asm-demo/src/main/java/com/yn/onlyvisit

测试类

package com.yn.onlyvisit; @CustomAnnotationOnClass public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CustomAnnotationOnClass { }

定义classVisitor,里面实现visitor的回调方法

package com.yn.onlyvisit; import org.objectweb.asm.*; import org.objectweb.asm.commons.AdviceAdapter; import org.objectweb.asm.commons.AnalyzerAdapter; import org.objectweb.asm.util.ASMifier; import org.objectweb.asm.util.Textifier; import org.objectweb.asm.util.TraceMethodVisitor; import java.util.ArrayList; import java.util.List; public class MyClassVistor extends ClassVisitor { private List<String> methodList = new ArrayList<>(); private List<String> annotationOnClass = new ArrayList<>(); public MyClassVistor() { super(Opcodes.ASM6); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { //每访问到一个方法,加入到field中 System.out.println("visitMethod: " + name); methodList.add(name); return super.visitMethod(access, name, desc, signature, exceptions); } @Override public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { // 访问到类上注解,加入field annotationOnClass.add(descriptor); return super.visitAnnotation(descriptor, visible); } @Override public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { System.out.println("field:" + name); return super.visitField(access, name, descriptor, signature, value); } public List<String> getMethodList() { return methodList; } public List<String> getAnnotationOnClass() { return annotationOnClass; } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfxsf.html