本文基于dubbo2.7.7分析
- dubbo SPI如何实现依赖注入
- 如何禁用dubbo的依赖注入
使用标准Setter方法依赖注入
dubbo的SPI默认支持依赖注入功能, 在SPI的实现类中,只要写标准的Setter方法即可, 示例如下:
public class CustomInterfaceImpl implements CustomInterface {
private CustomInterface2 customInterface2;
public void setCustomInterface2(CustomInterface2 customInterface2) {
this.customInterface2 = customInterface2;
}
@Override
public void print(String msg) {
log.info("CustomInterfaceImpl print");
}
}
dubbo查找依赖的对象来源默认支持两种方式,
- 一种是在和Spring整合时,支持从Spring中查找。
- 第二种是从Dubbo的SPI扩展中使用
ExtensionLoader#getAdaptiveExtension()
查找依赖的对象, 这种方式要求Setter方法的参数类型必须对应SPI接口(包含自定义的SPI接口).
public class CustomInterfaceImpl implements CustomInterface {
private org.apache.dubbo.common.compiler.Compiler compiler;
public void setCompiler(Compiler compiler) {
this.compiler = compiler;
}
@Override
public void print(String msg) {
log.info("CustomInterfaceImpl print");
}
}
使用@DisableInject
禁用Setter方法自动注入依赖
有时候在实现类中写了标准的Setter方法,但并不是想自动注入依赖。这种情况下就需要用到@DisableInject
注解。dubbo的org.apache.dubbo.common.config.Environment
中则使用了该注解。
源码分析
org.apache.dubbo.common.extension.ExtensionLoader#injectExtension
当通过ExtensionLoader
创建SPI实例化对象后,会调用ExtensionLoader#injectExtension(instance)
方法执行依赖注入.
如何查找依赖的对象
通过org.apache.dubbo.common.extension.ExtensionFactory
来实现查找,ExtensionFactory
本身也是一个SPI接口, 因此对于ExtensionFactory
的实现类不支持依赖注入,否则造成了死循环自己依赖自己。在ExtensionLoader
构造方法中会根据接口类型判断是否获取ExtensionFactory
实例,如果是ExtensionFactory
则不会获取, 否则获取ExtensionFactory
赋值给成员变量objectFactory用于查询依赖的实例,当执行依赖注入逻辑时, 如果objectFactory是null
,则不执行依赖注入,以此来规避循环依赖。
org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
AdaptiveExtensionFactory
通过ExtensionLoader#getSupportedExtensions
获取ExtensionFactory实现类集合,不会标记@Adaptive
的实现,即不会包含AdaptiveExtensionFactory
本身, 避免了循环依赖. 默认为以下两个实现:
org.apache.dubbo.common.extension.factory.SpiExtensionFactory
org.apache.dubbo.config.spring.extension.SpringExtensionFactory
调试时发现SpiExtensionFactory
优先于SpringExtensionFactory
执行,但是最好不要依赖这个顺序去实现自己的业务逻辑,因为dubbo在扫描SPI的实现类时内部是通过Map保存,无法保证顺序的。
org.apache.dubbo.common.extension.factory.SpiExtensionFactory
org.apache.dubbo.config.spring.extension.SpringExtensionFactory