一.dubbo的SPI机制
SPI机制是一个服务发现机制,通过接口的全限定名找到指定目录下对应的文件,然后加载对应的实现类注册到系统中进行使用。
在Java原生跟mysql的驱动加载也使用了这个机制,但是他们只能进行全部实现类的加载(遍历了所有的实现类并实例化),消耗了资源
- Dubbo优化了这个机制,使用了键值对的形式进行加载,实现了按需加载。
- 并且增加了缓存实例,提高读取性能
- 提供了对IOC和AOP等高级功能的支持,以实现更多类型的扩展
二.如何实现SPI机制
SPI服务提供接口是Java的重要机制,主要用于实现模块化开发和插件化扩展。
SPI机制允许服务提供者通过特定的配置文件将自己的实现注册到系统中,然后系统通过反射机制动态加载这些实现,而不需要修改原始框架的代码,从而实现了系统的解耦,提高了可扩展性。
一个典型的SPI应用场景是JDBC,不同的数据库驱动程序开发者可以使用JDBC库,然后定制自己的数据库驱动程序
此外,我们使用的主流Java开发框架中,几乎都使用了SPI机制,比如Servlet容器、日志框架、ORM框架、Spring框架
虽然Java内置了ServiceLoader来实现SPI,但是如果想定制多个不同的接口实现类。就没办法在框架中指定使用哪一个了,也就无法实现像”通过配置快速指定序列化器“这样的需求。
所以我自己定义了SPI机制的实现,能够给每个自行扩展的类指定键名。
比如读取如下配置文件,能够得到一个序列化器=>序列化器实现对象的映射。之后就可以根据用户配置的序列化器名称动态加载指定实现类对象了
具体实现方法如下:
1)指定SPI的配置目录,并且将配置再分为系统内置SPI和用户自定义SPI,便于区分优先级和维护。
2)编写SpiLoader加载器,实现读取配置、加载实现类的方法
- 用Map来存储已加载的配置信息 键名---实现类
- 通过Hutool工具库提供的ResourceUtil.getResources扫描指定路径,读取每个配置文件,获取到键名--实现类信息并存储再Map中。
- 定义获取实例方法,根据用户传入的接口和键名,从Map中找到相应的实现类,然后通过反射获取到实现类对象。可以维护一个对象实例缓存,创建过一次的对象从缓存中读取即可。
3)重构序列化器工厂,改为从SPI加载指定的序列化器对象