想在 dubbo filter里使用 spring bean,看看怎么做.
dubbo ExtensionFactory有一个 SpringExtensionFactory, 了解下dubbo spi机制。
术语:
SPI : Service Provider Interface 。
扩展点 : 称 Dubbo 中被 @SPI 注解的 Interface 为一个扩展点。
扩展 : 被 @SPI 注解的 Interface 的实现称为这个扩展点的一个扩展。
默认适应扩展 :
被 @SPI("abc") 注解的 Interface , 那么这个扩展点的缺省适应扩展就是 SPI 配置文件中 key 为 "abc" 的扩展。
如果存在被 @Adaptive 注解在类上的扩展点接口实现 ,那么这个类就作为扩展点的缺省适应扩展, 一个扩展点只能有一个缺省适应扩展也就是说多个扩展中只能有一个在类上被 @Adaptive 注解
如果有多个 dubbo 会抛出 IllegalStateException("More than 1 adaptive class found : ")。
约定
扩展点约定 :
扩展点必须是 Interface 类型 , 必须被 @SPI 注解 , 满足这两点才是一个扩展点。
扩展定义约定 :
1.在 META-INF/services/$扩展点接口的全类名
2.META-INF/dubbo/$扩展点接口的全类名
3.META-INF/dubbo/internal/$扩展点接口的全类名
以上路径下定义的文件名称为 $扩展点接口的全类名
文件中以键值对的方式配置扩展点的扩展实现
注解
@SPI (注解在类上) : @SPI 注解标识了接口是一个扩展点 , 属性 value 用来指定默认适配扩展点的名称。
@Activate (注解在类型和方法上) :
@Activate 注解在扩展点的实现类上 ,表示了一个扩展类被获取到的的条件,符合条件就被获取,不符合条件就不获取 ,根据 @Activate 中的 group 、 value 属性来过滤 。具体参考 ExtensionLoader 中的 getActivateExtension 函数。
@Adaptive (注解在类型和方法上) :
@Adaptive 注解在类上 , 这个类就是缺省的适配扩展。
@Adaptive 注解在扩展点 Interface 的方法上时 , dubbo 动态的生成一个这个扩展点的适配扩展类(生成代码 ,动态编译实例化 Class ),名称为 扩展点 Interface 的简单类名 + $Adaptive ,例如 : ProxyFactory$Adpative 。这么做的目的是为了在运行时去适配不同的扩展实例 , 在运行时通过传入的 URL 类型的参数或者内部含有获取 URL 方法的参数 ,从 URL 中获取到要使用的扩展类的名称 ,再去根据名称加载对应的扩展实例 ,用这个扩展实例对象调用相同的方法 。如果运行时没有适配到运行的扩展实例 , 那么就使用 @SPI 注解缺省指定的扩展。通过这种方式就实现了运行时去适配到对应的扩展。
例子
@Activate 例子:
filter上, @Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.CACHE_KEY)
@Adaptive 例子:
注解在类上
ExtensionLoader.objectFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
得到的实例是 AdaptiveExtensionFactory , AdaptiveExtensionFactory类上标注了@Adaptive, 属于扩展点的默认实现
注解在扩展点 Interface 的方法上
com.alibaba.dubbo.rpc.Protocol.class, export 和 refer 方法。动态生成了 Protocol$Adaptive 类,代码如下
wapper类
ExtensionLoader.loadClass 有一段
private boolean isWrapperClass(Class> clazz) {
try {
clazz.getConstructor(type); return true; } catch (NoSuchMethodException e) { return false; }
}
cachedWrapperClasses 用在了, getExtension(String name) -> createExtension(String name)
如 Protocol$Adaptive里 , getExtension("dubbo"), 调用了相关的wapper , ProtocolFilterWrapper 、ProtocolListenerWrapper、QosProtocolWrapper
依赖注入
injectExtension(T instance)
继续看, AdaptiveExtensionFactory, AdaptiveExtensionFactory是个composite类, 包含 SpiExtensionFactory和SpringExtensionFactory,可以通过 SpringExtensionFactory 获得bean吗?
ServiceBean.setApplicationContext 调用了, SpringExtensionFactory.addApplicationContext(applicationContext);
ServiceBean和dubbo、spring的服务暴露有关
测试使用 spring bean
1.
ApplicationContext context= ServiceBean.getSpringContext();
InternalAccessConfig config = context.getBean(InternalAccessConfig.class);
2.
ExtensionFactory objectFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
InternalAccessConfig config = objectFactory.getExtension(InternalAccessConfig.class, "internalAccessConfig");
两个方式都可以。