扩展点自适应
介绍
ExtensionLoader注入的依赖扩展点是一个Adaptive实例,直到扩展点方法执行时才决定调用是哪一个扩展点实现。
dubbo使用url对象传递对象信息,包含key和value。
扩展点方法调用会有URL参数(或是参数有URL成员)这样依赖的扩展点也可以从URL拿到配置信息,所有的扩展点自己定好配置的 Key后,配置信息从URL上从最外层传入。URL在配置传递上即是一条总线。
@Adaptive注解
表示该类是一个扩展类(Adaptive实例),不需要生成代理方法直接使用即可。
在方法上则表示该方法需生成代理, 此时就需要用到上面提到的URL参数。
如果作用在方法会帮我们在运行时动态生成一个Adaptive实例(只包含扩展方法的),如果作用在类上就相当于自己定义了一个现成的。
注解在实现类上
表示该类是一个扩展类,不需要生成代理方法直接使用即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @SPI public interface AdaptiveService { void sayHello(); }
@Adaptive public class AdaptiveServiceImpl implements AdaptiveService {
@Override public void sayHello(){ System.out.println("hello"); } }
AdaptiveService=com.lin.extendAdaptive.extend.impl.AdaptiveServiceImpl
public class ExtendAdaptiveMain {
public static void main(String[] args) { ExtensionLoader<AdaptiveService> extensionLoader = ExtensionLoader.getExtensionLoader(AdaptiveService.class); AdaptiveService adaptiveExtension = extensionLoader.getAdaptiveExtension(); adaptiveExtension.sayHello(); } }
|
注解在接口方法上
在方法上则表示该方法需生成代理, 此时就需要用到上面提到的URL参数。
当注解在接口方法上时,方法中需要传入一个URL参数,或者包装有URL参数时,会通过动态编译获得一个Adaptive实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| @SPI public interface MethodAdaptiveService {
@Adaptive({"key"}) void sayHello(URL url); }
public class MethodAdaptiveServiceImpl implements MethodAdaptiveService {
@Override public void sayHello(URL url){ System.out.println("method"); } }
MethodAdaptiveService=com.lin.extendAdaptive.extend.impl.MethodAdaptiveServiceImpl
public static void main(String[] args) { ExtensionLoader<MethodAdaptiveService> extensionLoader = ExtensionLoader.getExtensionLoader(MethodAdaptiveService.class); MethodAdaptiveService adaptiveExtension = extensionLoader.getAdaptiveExtension(); HashMap hashMap = new HashMap(); hashMap.put("key","MethodAdaptiveService"); URL url = new URL("dubbo","localhost",8080,hashMap); adaptiveExtension.sayHello(url); }
package com.lin.extendAdaptive.extend; import org.apache.dubbo.common.extension.ExtensionLoader; public class MethodAdaptiveService$Adaptive implements com.lin.extendAdaptive.extend.MethodAdaptiveService { public void sayHello(org.apache.dubbo.common.URL arg0) { if (arg0 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg0; String extName = url.getParameter("key"); if(extName == null) throw new IllegalStateException("Failed to get extension (com.lin.extendAdaptive.extend.MethodAdaptiveService) name from url (" + url.toString() + ") use keys([key])"); com.lin.extendAdaptive.extend.MethodAdaptiveService extension = (com.lin.extendAdaptive.extend.MethodAdaptiveService)ExtensionLoader.getExtensionLoader(com.lin.extendAdaptive.extend.MethodAdaptiveService.class).getExtension(extName); extension.sayHello(url); } }, dubbo version: 2.7.1, current host: 192.168.139.15
|
程序运行时,会经过动态编译过程生成MethodAdaptiveService对应的Adaptive实例,即MethodAdaptiveService$Adaptive。
就是在程序运行过程中,根据条件,通过拼接字符串的形式生成java源码,然后进行编译获得对应的实例。
扩展点自动注入
有bug稍后。