本文共 3881 字,大约阅读时间需要 12 分钟。
在上一篇文章中,我们分析了 Dubbo SPI 中 Expansion Point 的实现,特别关注 ExtensionLoader 如何通过 getExtension(String name) 方法获取扩展点实现类对象。本文将深入探讨 Dubbo 源码中的 getAdaptiveExtension() 方法,以及它如何支持自适应扩展点的实例化和注入。
在 ExtensionLoader 中,与扩展相关的实例缓存和实现类缓存是关键组件。以下是代码中定义的相关部分:
// 自适应扩展点实例缓存private final Holder< Object > cachedAdaptiveInstance = new Holder<>();// 自适应扩展点实现类的类加载类别private volatile Class> cachedAdaptiveClass = null;
缓存机制显著提升了扩展点的性能表现,减少了重复计算和资源浪费。
要获取自适应扩展点实例,ExtensionLoader 提供了 getAdaptiveExtension() 方法,其实现逻辑如下:
public T getAdaptiveExtension() { // 从缓存中获取现有实例 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { // 调用异常处理方法检查 if (createAdaptiveInstanceError != null) { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } // 通过锁同步机制确保 thread-safety synchronized (cachedAdaptiveInstance) { // 再次从缓存中获取实例 instance = cachedAdaptiveInstance.get(); if (instance == null) { // 创建新实例 try { instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } return (T) instance;} 自适应扩展点的实例化涉及以下步骤:
private T createAdaptiveExtension() { try { // 获取自适应扩展点的实现类 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); }} 与上一篇文章类似,getAdaptiveExtensionClass() 方法负责获取合适的扩展点实现类:
private Class> getAdaptiveExtensionClass() { // 加载已存在的实现类 getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } //ync动态编译生成新实现类 return cachedAdaptiveClass = createAdaptiveExtensionClass();} 为了支持动态编译,createAdaptiveExtensionClass() 会生成自适应扩展点的实现类:
private Class> createAdaptiveExtensionClass() { // 使用自定义编译工具生成插件 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); ClassLoader classLoader = findClassLoader(); org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(Compiler.class).getAdaptiveExtension(); return compiler.compile(code, classLoader);} 生成的代码实现会自动引用所需扩展点,以支持灵活配置和注入。
最后,injectExtension() 方法负责注入所需的扩展点实例:
private T injectExtension(T instance) { if (objectFactory == null) { return instance; } // 通过反射检查并注入属性 for (Method method : instance.getClass().getMethods()) { if (!isSetter(method)) { continue; } if (method.getAnnotation(DisableInject.class) != null) { continue; } Class pt = method.getParameterTypes()[0]; if (ReflectUtils.isPrimitives(pt)) { continue; } try { // 从对象工厂获取相关扩展实例 Object object = objectFactory.getExtension(pt, getProperty()); 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); } } return instance;} 通过在 ExtensionLoader 中实现 cache 算法和动态编译机制,Dubbo 为自适应扩展点提供了高度的灵活性和性能优化。缓存显著减少了重复计算,动态编译支持了扩展点的灵活继承。这种设计理念不仅提升了扩展点的性能表现,还为开发者提供了更强大的灵活性和可编程性。
转载地址:http://ugpdz.baihongyu.com/