前景回顾
当我们把写好的业务代码交给 Spring 之后, Spring 都会做些什么呢?
仔细想象一下, 再稍微抽象一下, Spring 所做的几乎全部都是:
"bean 的实例化, bean 的依赖装配, bean 的初始化, bean 的方法调用, bean 的销毁回收".
那问题来了, Spring 为什么能够准确无误的完成这波对 bean 的操作呢? 答案很简单, 就是:
"Spring 掌握了有关 bean 的足够多的信息".
这就是本系列文章第一篇 "帝国的基石" 的核心思想. Spring 通过 bean 定义的概念收集到了 bean 的全部信息.
这件事也说明, 当我们拥有了一个事物的大量有效信息之后, 就可以做出一些非常有价值的操作. 如大数据分析, 用户画像等.
紧接着就是第二个问题, Spring 应该采用什么样的方式来收集 bean 的信息呢?
这就是本系列文章第二篇 "bean 定义上梁山" 主要讲的内容.
首先是统一了编程模型, 只要是围绕 Spring 的开发, 包括框架自身的开发, 最后大都转化为 bean 定义的注册.
为了满足不同的场景, Spring 提供了两大类的 bean 定义注册方式:
实现指定接口, 采用写代码的方式来注册, 这是非常灵活的动态注册, 根据不同的条件注册不同的 bean, 主要用于第三方组件和 Spring 的整合.
标上指定注解, 采用注解扫描的方式来注册, 这相当于一种静态的注册, 非常不灵活, 但特别简单易用, 主要用于普通业务代码的开发.
Spring 设计的这一切, 看起来确实完美, 用起来也确实很爽, 但实现起来呢, 也确实的非常麻烦.
尤其是在全部采用注解和 Java 配置的时候, 那才叫一个繁琐, 看看源码便知一二.
所以本篇及接下来的几篇都会写一些和实现细节相关的内容, 俗称 "干货", 哈哈.
最容易想到的实现方案
一个 bean 其实就是一个类, 所以 bean 的信息就是类的信息.
那一个类都有哪些信息呢, 闭着眼睛都能说出来, 共四大类信息:
类型信息, 类名, 父类, 实现的接口, 访问控制 / 修饰符
字段信息, 字段名, 字段类型, 访问控制 / 修饰符
方法信息, 方法名, 返回类型, 参数类型, 访问控制 / 修饰符
注解信息, 类上的注解, 字段上的注解, 方法上的注解 / 方法参数上的注解
注: 还有内部类 / 外部类这些信息, 也是非常重要的.
看到这里脑海中应该立马蹦出两个字, 没错, 就是反射.
但是, Spring 并没有采用反射来获取这些信息, 个人认为可能有以下两个大的原因:
性能损耗问题:
要想使用反射, JVM 必须先加载类, 然后生成对应的 Class<?> 对象, 最后缓存起来.
实际的工程可能会注册较多的 bean, 但是真正运行时不一定都会用得到.
所以 JVM 加载过多的类, 不仅会耗费较多的时间, 还会占用较多的内存, 而且加载的类很多可能都不用.
信息完整度问题:
JDK 在 1.8 版本中新增加了一些和反射相关的 API, 比如和方法参数名称相关的. 此时才能使用反射获取相对完善的信息.
但 Spring 很早就提供了对注解的支持, 所以当时的反射并不完善, 也可能是通过反射获取到的信息并不能完全符合要求.
总之, Spring 没有选择反射.
那如何获取类的这些信息呢? 答案应该只剩一种, 就是直接从字节码文件中获取.
采用先进的生产力
源码经过编译变成字节码, 所以源码中有的信息, 在字节码中肯定都有. 只不过换了一种存在的形式.
Java 源码遵循 Java 语法规范, 生成的字节码遵循 JVM 中的字节码规范.
字节码文件的结构确实有些复杂, 应用程序想要直接从字节码中读出需要的信息也确实有些困难.
小平同志曾说过,"科学技术是第一生产力". 所以要解决复杂的问题, 必须要有比较可靠的技术才行.
对于复杂的字节码来说, 先进的生产力就是 ASM 了. ASM 是一个小巧快速的 Java 字节码操作框架.
它既可以读字节码文件, 也可以写字节码文件. Spring 框架主要用它来读取字节码.
ASM 框架是采用访问者模式设计出来的, 如果不熟悉这个设计模式的可以阅读本公众号上一篇文章 "趣说访问者模式".
该模式的核心思想就是, 访问者按照一定的规则顺序进行访问, 期间会自动获取到相关信息, 把有用的信息保存下来即可.
下面介绍一下 ASM 的具体使用方式, 可以看看作为了解, 说不定以后会用到. 哈哈.
ASM 定义了 ClassVisitor 来获取类型信息, AnnotationVisitor 来获取注解信息, FieldVisitor 来获取字段信息, MethodVisitor 来获取方法信息.
先准备好产生字节码的素材, 其实就是一个类啦, 这个类仅作测试使用, 不用考虑是否合理, 如下:
来源: http://www.bubuko.com/infodetail-3214926.html