
文章插图
RedisProperties 中维护了 Redis 连接所需要的关键属性,只要在 yml 或 properties 配置文件中,指定 spring.redis 开头的属性,都会被自动装载到 RedisProperties 实例中 。

文章插图
通过以上分析,已经一步步解读出 Spring Boot 自动装载的原理 。
五、SPI 应用案例之 DubboDubbo 并未使用 Java SPI,而是自己封装了一套新的 SPI 机制 。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下,配置内容形式如下:
optimusPrime = org.apache.spi.OptimusPrimebumblebee = org.apache.spi.Bumblebee与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置,这样可以按需加载指定的实现类 。Dubbo SPI 除了支持按需加载接口实现类,还增加了 IOC 和 AOP 等特性 。
5.1 ExtensionLoader 入口Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,可以加载指定的实现类 。
ExtensionLoader 的 getExtension 方法是其入口方法,其源码如下:
public T getExtension(String name) {if (name == null || name.length() == 0)throw new IllegalArgumentException("Extension name == null");if ("true".equals(name)) {// 获取默认的拓展实现类return getDefaultExtension();}// Holder,顾名思义,用于持有目标对象Holder<Object> holder = cachedInstances.get(name);if (holder == null) {cachedInstances.putIfAbsent(name, new Holder<Object>());holder = cachedInstances.get(name);}Object instance = holder.get();// 双重检查if (instance == null) {synchronized (holder) {instance = holder.get();if (instance == null) {// 创建拓展实例instance = createExtension(name);// 设置实例到 holder 中holder.set(instance);}}}return (T) instance;}可以看出,这个方法的作用就是:首先检查缓存,缓存未命中则调用 createExtension 方法创建拓展对象 。那么,createExtension 是如何创建拓展对象的呢,其源码如下:
private T createExtension(String name) {// 从配置文件中加载所有的拓展类,可得到“配置项名称”到“配置类”的映射关系表Class<?> clazz = getExtensionClasses().get(name);if (clazz == null) {throw findException(name);}try {T instance = (T) EXTENSION_INSTANCES.get(clazz);if (instance == null) {// 通过反射创建实例EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());instance = (T) EXTENSION_INSTANCES.get(clazz);}// 向实例中注入依赖injectExtension(instance);Set<Class<?>> wrapperClasses = cachedWrapperClasses;if (wrapperClasses != null && !wrapperClasses.isEmpty()) {// 循环创建 Wrapper 实例for (Class<?> wrapperClass : wrapperClasses) {// 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例 。// 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));}}return instance;} catch (Throwable t) {throw new IllegalStateException("...");}}createExtension 方法的的工作步骤可以归纳为:
- 通过 getExtensionClasses 获取所有的拓展类
- 通过反射创建拓展对象
- 向拓展对象中注入依赖
- 将拓展对象包裹在相应的 Wrapper 对象中
5.2 获取所有的拓展类Dubbo 在通过名称获取拓展类之前,首先需要根据配置文件解析出拓展项名称到拓展类的映射关系表(Map<名称, 拓展类>),之后再根据拓展项名称从映射关系表中取出相应的拓展类即可 。相关过程的代码分析如下:
经验总结扩展阅读
- 10月28日3时42分新疆阿克苏地区沙雅县发生3.0级地震
- 10月28日4时34分新疆阿克苏地区温宿县发生3.0级地震
- 今年第22号台风“尼格”最强可达台风级 30日傍晚前后进入南海海面
- 红米note9pro评测最新_红米note9pro深度测评
- 空调一级能效与三级能效的区别是什么
- iOS 16.3.1正式版续航怎么样 iOS 16.3.1升级建议
- ipx7和ip68哪个更防水 哪个防水等级更高
- 10月28日今起三天陕西持续阴雨模式局地阵风6级 风寒效应明显需保暖
- EasyPoi大数据导入导出百万级实例
- Dubbo-聊聊通信模块设计