Dubbo SPI的基本工作流程:
-
加载扩展点配置:Dubbo SPI首先会加载所有的扩展点配置,这些配置通常是在META-INF/dubbo目录下的properties文件中定义的。每个配置文件的名称就是扩展点接口的全限定名,文件内容是扩展点实现的键值对,键是扩展点的名称,值是扩展点实现类的全限定名。
-
创建扩展点实例:当用户获取一个扩展点时,Dubbo SPI会根据配置文件创建一个扩展点实例。如果配置文件中定义了多个扩展点实现,用户可以通过扩展点的名称获取特定的实现。
-
注入依赖:Dubbo SPI支持对扩展点实例进行依赖注入。如果扩展点实现类有其他扩展点的依赖,Dubbo SPI会自动将这些依赖注入到实例中。
-
包装扩展点:Dubbo SPI还支持对扩展点进行包装。用户可以定义一个包装类,这个类需要有一个接受原始扩展点实例的构造方法。当用户获取扩展点时,Dubbo SPI会自动用包装类包装原始的扩展点实例。
Dubbo SPI主要支持两种类型的依赖注入:
-
Setter注入:这是最常见的一种依赖注入方式。在扩展点实现类中,如果有一个public的setter方法,且方法的参数类型是另一个扩展点接口,那么Dubbo SPI会自动调用这个setter方法,将对应的扩展点实例注入进去。例如,如果有一个setter方法是
setFilter(Filter filter)
,那么Dubbo SPI会自动创建一个Filter的扩展点实例,并通过这个setter方法注入。 -
构造方法注入:除了setter注入,Dubbo SPI还支持通过构造方法进行依赖注入。如果扩展点实现类有一个构造方法,且这个构造方法的参数类型是另一个扩展点接口,那么Dubbo SPI也会自动创建一个对应的扩展点实例,并通过这个构造方法注入。例如,如果有一个构造方法是
MyExtension(Filter filter)
,那么Dubbo SPI也会自动创建一个Filter的扩展点实例,并通过这个构造方法注入。
不支持setter方法和构造方法注入的情况下,Dubbo SPI如何实现依赖注入?
如果一个扩展点实现类既没有合适的setter方法,也没有合适的构造方法,那么Dubbo SPI是无法直接进行依赖注入的。在这种情况下,我们需要手动进行依赖注入。
Dubbo SPI提供了一个名为ExtensionLoader
的类,这个类提供了一系列的方法,可以用来获取扩展点实例。例如,ExtensionLoader.getExtensionLoader(Filter.class).getExtension("myFilter")
可以获取名为"myFilter"的Filter扩展点实例。
我们可以在扩展点实现类的初始化代码中,使用这种方式手动获取需要的扩展点实例,并进行依赖注入。虽然这种方式比较麻烦,但是它提供了更大的灵活性,可以应对更复杂的依赖关系。
需要注意的是,手动依赖注入的方式并不推荐,因为它增加了代码的复杂性,并且可能导致依赖关系的管理变得困难。在大多数情况下,我们都应该优先使用setter方法或构造方法进行依赖注入。