2024年最新追踪解析 Dubbo 的 Spi 机制源码,成功从三线小公司跳进大厂涨薪8K

最后如何让自己一步步成为技术专家

说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。

当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。

推荐一份Java架构之路必备的学习笔记,内容相当全面!!!

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

// 如果之前初始化的时候报错了,那么错误会被记录下来并缓存在此处,直接抛出

// 此处的设计应该是减少锁消耗

if (createAdaptiveInstanceError != null) {

throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(),

createAdaptiveInstanceError);

}

synchronized (cachedAdaptiveInstance) {

// 双锁验证

instance = cachedAdaptiveInstance.get();

if (instance == null) {

try {

// 创建实例并存储在 Holder 对象里

instance = createAdaptiveExtension();

cachedAdaptiveInstance.set(instance);

} catch (Throwable t) {

// 如果报错了就会把错误存储起来

createAdaptiveInstanceError = t;

throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);

}

}

}

}

// 返回对象实例

return (T) instance;

}

2 createAdaptiveExtension

创建实例对象:

// org.apache.dubbo.common.extension.ExtensionLoader

private T createAdaptiveExtension() {

try {

// getAdaptiveExtensionClass().newInstance() 方法会使用 Class 对象的 newInstance() 方法创建一个对象

// injectExtension(…) 则会对创建出来的对象进行依赖注入

return injectExtension((T)getAdaptiveExtensionClass().newInstance());

} catch (Exception e) {

throw new IllegalStateException("Can’t create adaptive extension " + type + ", cause: " + e.getMessage(), e);

}

}

3 injectExtension

// org.apache.dubbo.common.extension.ExtensionLoader

private T injectExtension(T instance) {

// objectFactory 是用来依赖注入的 ExtensionFactory

// 如果 objectFactory 为空,就直接返回

// 需要注意的是,只有非 ExtensionFactory 的 loader 才有 objectFactory

if (objectFactory == null) {

return instance;

}

try {

// 轮训实例对象中所有的方法

for (Method method : instance.getClass().getMethods()) {

// 如果方法不是 set 方法就跳过

// 此处可以理解为,dubbo 的 spi 依赖注入需要 set 方法支持

if (!isSetter(method)) {

continue;

}

// 如果方法被标注了 DisableInject 注解就跳过

if (method.getAnnotation(DisableInject.class) != null) {

continue;

}

// 如果方法的参数是原始类型就跳过

// 依赖注入需要使用包装类型

Class<?> pt = method.getParameterTypes()[0];

if (ReflectUtils.isPrimitives(pt)) {

continue;

}

try {

// 反射注入

String property = getSetterProperty(method);

Object object = objectFactory.getExtension(pt, property);

if (object != null) {

method.invoke(instance, object);

}

} catch (Exception e) {

logger.error("Failed to inject via method " + method.getName()

  • " of interface " + type.getName() + ": " + e.getMessage(), e);

}

}

} catch (Exception e) {

logger.error(e.getMessage(), e);

}

return instance;

}

##三 ExtensionFactory

ExtensionFactory 是用来依赖注入的工厂:

@SPI

public interface ExtensionFactory {

T getExtension(Class type, String name);

}

该接口在 Dubbo 中有三个默认实现类:

org.apache.dubbo.config.spring.extension.SpringExtensionFactory

org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory

org.apache.dubbo.common.extension.factory.SpiExtensionFactory

在开发中 SpringExtensionFactory 应该会用的更广泛一些,本示例中此处暂时不展开。

1 AdaptiveExtensionFactory

AdaptiveExtensionFactory 是默认工厂:

import org.apache.dubbo.common.extension.Adaptive;

import org.apache.dubbo.common.extension.ExtensionFactory;

import org.apache.dubbo.common.extension.ExtensionLoader;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

@Adaptive

public class AdaptiveExtensionFactory implements ExtensionFactory {

private final List factories;

// 构造器

public AdaptiveExtensionFactory() {

ExtensionLoader loader

= ExtensionLoader

.getExtensionLoader(ExtensionFactory.class);

// AdaptiveExtensionFactory 会将 SpiExtensionFactory 和 SpringExtensionFactory 放置在 factories 列表里

List list = new ArrayList();

for (String name : loader.getSupportedExtensions()) {

list.add(loader.getExtension(name));

}

factories = Collections.unmodifiableList(list);

}

// 使用 AdaptiveExtensionFactory 去获取实体类的时候,

// 会调用 spi 或者 spring 的 ext 工厂去尝试获取实体类

@Override

public T getExtension(Class type, String name) {

for (ExtensionFactory factory : factories) {

T extension = factory.getExtension(type, name);

if (extension != null) {

return extension;

}

}

return null;

}

}

2 SpiExtensionFactory

import org.apache.dubbo.common.extension.ExtensionFactory;

import org.apache.dubbo.common.extension.ExtensionLoader;

import org.apache.dubbo.common.extension.SPI;

public class SpiExtensionFactory implements ExtensionFactory {

@Override

public T getExtension(Class type, String name) {

// spi 工厂用于解析 spi 注解

if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {

// 如果传入的 type 是一个被 spi 注释的接口,那么会初始化一个它的 class loader

ExtensionLoader loader

= ExtensionLoader.getExtensionLoader(type);

// 初始化对象

if (!loader.getSupportedExtensions().isEmpty()) {

return loader.getAdaptiveExtension();

}

}

return null;

}

}

##四 getExtension

回到 demo :

SpiDemoService one = loader.getExtension(“one”);

1 getExtension

// org.apache.dubbo.common.extension.ExtensionLoader

public T getExtension(String name) {

// 非空验证,忽略

if (StringUtils.isEmpty(name)) {

throw new IllegalArgumentException(“Extension name == null”);

}

// 默认机制,会去找名称为 dubbo 的实例

// 一般用不到

if (“true”.equals(name)) {

return getDefaultExtension();

}

// 如果之前不存在这个名称对应的 Holder 对象,此处会创建一个空白的 Holder

// 调用 get() 方法会获得空对象

final Holder holder = getOrCreateHolder(name);

Object instance = holder.get();

if (instance == null) {

synchronized (holder) {

instance = holder.get();

if (instance == null) {

// 创建对象实例,并装进 holder 中

instance = createExtension(name);

holder.set(instance);

}

}

}

// 返回实例

return (T) instance;

}

2 createExtension

// org.apache.dubbo.common.extension.ExtensionLoader

private T createExtension(String name) {

// 如果 class 不存在就报错

Class<?> clazz = getExtensionClasses().get(name);

if (clazz == null) {

throw findException(name);

}

try {

// 尝试获取 class 对应的实例,如果不存在就创建

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 (CollectionUtils.isNotEmpty(wrapperClasses)) {

for (Class<?> wrapperClass : wrapperClasses) {

instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));

}

}

initExtension(instance);

return instance;

} catch (Throwable t) {

throw new IllegalStateException("Extension instance (name: " + name + ", class: " +

type + ") couldn’t be instantiated: " + t.getMessage(), t);

}

}

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

able t) {

throw new IllegalStateException("Extension instance (name: " + name + ", class: " +

type + ") couldn’t be instantiated: " + t.getMessage(), t);

}

}

[外链图片转存中…(img-F8w1RtT1-1715258418392)]

最近我根据上述的技术体系图搜集了几十套腾讯、头条、阿里、美团等公司21年的面试题,把技术点整理成了视频(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分

[外链图片转存中…(img-vDVCGKto-1715258418393)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值