dubbo扩展点SPI的源码分析
目录SPI描述和使用
简介: 读取meta-inf/dubbo/internal/
,meta-inf/dubbo/
,meta-inf/services/
文件夹下的文件,文件名:就是要加载的类名,文件内容以key=value形式储存,value是加载类的实现类和包装类,key为value的标识。怎么识别是不是包装类呢?包装类的构建方法是有参的,该参数是要加载的对象。实现类是无参构建的。SPI的有三钟方式进行使用
- 指定名字的扩展点
- 自适应扩展点
- 激活扩展点
指定名字的扩展点
描述: 传入要加载的类和名字就能得到加载类的实现类
使用方式:
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("dubbo")
自适应扩展点
描述: 只需要传入类名,通过自适应的方式去获取。 如果实现的类名上加了@Adaptive,那么默认返回的就是改实现类对象,如果都没加上的话,以Protocol为例,他会生成一个Protocol$Adaptive,Protocol$Adaptive.export()方法大体是:通过传进来Invoker,得到了URL,因此也能得到相应的协议的名字,然后再通过改名字,去通过指定名字的扩展点去获取实现类,实现类去调用export()。其他方法也是差不多大概的逻辑
使用方式:
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()
激活扩展点
相当于Spring中的conditional
使用方法:
URL url = new URL("dubbo", "", 0);
url = url.addParameter("cache","A");
url = url.addParameter("cacheA","ABC");
//返回的是B
List<InterfaceService> activateExtension = ExtensionLoader.getExtensionLoader(InterfaceService.class).getActivateExtension(url,"cache1");
System.err.println(activateExtension);
//返回的是A和B
List<InterfaceService> activateExtension1 = ExtensionLoader.getExtensionLoader(InterfaceService.class).getActivateExtension(url,"cache");
System.err.println(activateExtension1);
InterfaceService类型:
@Activate(value = "ABC")
public class AService implements InterfaceService{
}
@Activate(value = "cacheA:ABC")//这里是需要key:value形式的
public class BService implements InterfaceService {
}
public class CService implements InterfaceService {
}
meta-inf/dubbo/internal/com.onion.service.InterfaceService文件:
A=com.onion.service.AService
B=com.onion.service.BService
C=com.onion.service.CService
注意:
- 不带@Activate注解是无法加载到的
- @Activate里面的value和group为null的时候,代表默认会加载返回
- getActivateExtension(url,"cache") 方法中里key是cache,如果跟 url = url.addParameter("cache","A");中也存在cache,那么A一定要有存在于
meta-inf/dubbo/internal/com.onion.service.InterfaceService
文件中的key里,如果没有的话就会报错 ----- 因为代码会通过指定名字扩展点去获取A,如果获取不倒就会报错的。 - @Activate的value的形式要按照:key:value来,不然就会匹配不上的
- @Activate里value值是key:value形式的数组,url参数是key=value,然后对比各自的key和value,如果匹配上就能匹配上返回
ExtensionLoader一些成员变量的说明
//针对于指定名字扩展点的,key为指定的名字,value为指定名字的对象
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap();
//key为指定的名字,value为指定名字的类,-->赋值的在:loadclass的时候就会把他保存起来
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder();
//key为类名,value为对象名。
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap(64);、
//自适应扩展点中,如果实现类带有@Adaptive就会缓存起来,-->赋值的在:loadclass的时候就会把他保存起来
private volatile Class<?> cachedAdaptiveClass = null;
//包装类集合: -->赋值的在:loadclass的时候就会把他保存起来
private Set<Class<?>> cachedWrapperClasses;
//保存ExtensionLoader.getExtensionLoader(type)中的type
private final Class<?> type;
//存储自适应扩展点新增出来的对象
private final Holder<Object> cachedAdaptiveInstance = new Holder();
//带有@Activate注解的实现类 -->赋值的在:loadclass的时候就会把他保存起来
private final Map<String, Object> cachedActivates = new ConcurrentHashMap();
ExtensionLoader.getExtensionLoader 解析
ExtensionLoader类中:
private final Class<?> type;
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap(64);
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
//type问题的异常处理
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
} else if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
} else if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
} else {
ExtensionLoader<T> loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type)); //新建一个ExtensionLoader返回
loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
}
return loader;
}
}
private ExtensionLoader(Class<?> type) {
this.type = type; //会保存存进来的类放到type里面。
this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); //this.objectFactory就
}
getExtensionLoader功能介绍:保存type,如果type不是ExtensionFactory情况下,objectFactory其实就是AdaptiveExtensionFactory,因为AdaptiveExtensionFactory带了@Adaptive,objectFactory用途就是依赖注入的时候用来创建相应的对象的。
AdaptiveExtensionFactory作用:遍历其他的实现类,看下哪个可以实现类可以去创建依赖注入对象,相当于是一个管理ExtensionFactory的管理员
其中有个两个比较重要的实现类:
SpiExtensionFactory
:通过自适应扩展点去新建SpringExtensionFactory
:通过spirng容器里看下有没有这个对象有就返回
指定名字的扩展点解析
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(extName)
ExtensionLoader方法中:
public T getExtension(String name) {
return this.getExtension(name, true);
}
public T getExtension(String name, boolean wrap) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
} else if ("true".equals(name)) {
return this.getDefaultExtension();
} else {
//通过名字拿到holder
Holder<Object> holder = this.getorCreateHolder(name);
Object instance = holder.get();
//instance为空则新增一个,并且放到holder里
if (instance == null) {
synchronized(holder) {
instance = holder.get();
if (instance == null) {
instance = this.createExtension(name, wrap);
holder.set(instance);
}
}
}
return instance;
}
}
//通过名字读取缓存,如果有则返回,没有则新建一个 new Holder()返回
private Holder<Object> getorCreateHolder(String name) {
Holder<Object> holder = (Holder)this.cachedInstances.get(name);
if (holder == null) {
this.cachedInstances.putIfAbsent(name, new Holder());
holder = (Holder)this.cachedInstances.get(name);
}
return holder;
}
//通过名字创建一个instance
private T createExtension(String name, boolean wrap) {
//通过名字查看有没有缓存下来的类。
Class<?> clazz = (Class)this.getExtensionClasses().get(name);
if (clazz == null) {
throw this.findException(name);
} else {
try {
//通过类名查看有没有缓存下来的对象
T instance = EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
//通过反射新建一个对象
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = EXTENSION_INSTANCES.get(clazz);
}
//依赖注入成员变量
this.injectExtension(instance);
if (wrap) {
....包装instance,下面有详细介绍...
}
this.initExtension(instance);
return instance;
} catch (Throwable var9) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " + this.type + ") Couldn't be instantiated: " + var9.getMessage(), var9);
}
}
}
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = (Map)this.cachedClasses.get();
if (classes == null) {
synchronized(this.cachedClasses) {
classes = (Map)this.cachedClasses.get();
if (classes == null) {
classes = this.loadExtensionClasses();
this.cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
this.cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap();
LoadingStrategy[] var2 = strategies;
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
LoadingStrategy strategy = var2[var4];
this.loadDirectory(extensionClasses, strategy.directory(), this.type.getName(),
strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
this.loadDirectory(extensionClasses, strategy.directory(), this.type.getName().replace("org.apache", "com.alibaba"),
strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
}
return extensionClasses;
}
getExtension方法是: 利用指定的名字,看下有没有缓存的对象(getorCzhreateHolder方法实现),有的话直接返回,没有则创建(createExtension方法实现)。
总结:其实整体步骤就是看下通过指定的名字,看下有没有缓存下来的对象,没有则看下有没有缓存起来的类名信息集合Map,没有则读取相应文件,然后得到名字对应的类名,接着通过反射来新建对象,然后再依赖注入该对象的成员变量,如果有包装类则用包装类包装该对象返回
loadExtensionClasses读取文件加载类名到内存中
ExtensionLoader类名:
private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();
private static LoadingStrategy[] loadLoadingStrategies() {
//通过java的spi来获取
return (LoadingStrategy[])StreamSupport.stream(ServiceLoader.load(LoadingStrategy.class).spliterator(), false).sorted().toArray((x$0) -> {
return new LoadingStrategy[x$0];
});
}
private Map<String, Class<?>> loadExtensionClasses() {
this.cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap();
LoadingStrategy[] var2 = strategies;
int var3 = var2.length;
//遍历读取文件夹,文件夹有:`meta-inf/dubbo/internal/`,`meta-inf/dubbo/`,`meta-inf/services/`
for(int var4 = 0; var4 < var3; ++var4) {
LoadingStrategy strategy = var2[var4];
this.loadDirectory(extensionClasses, strategy.directory(), this.type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
this.loadDirectory(extensionClasses, strategy.directory(), this.type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
}
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type, boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
//文件名就是目录名加类名
String fileName = dir + type;
try {
Enumeration<java.net.URL> urls = null;
ClassLoader classLoader = findClassLoader();
//一系列手段去加载文件名得到url,
//ExtensionLoader.class.getClassLoader().getResources(fileName)
//classLoader.getResources(fileName)和ClassLoader.getSystemResources(fileName);
....
if (urls != null) {
while(urls.hasMoreElements()) {
java.net.URL resourceURL = (java.net.URL)urls.nextElement();
//读取文件资源
this.loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
}
}
} catch (Throwable var11) {
logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", var11);
}
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8));
Throwable var7 = null;
try {
String line;
try {
//读取文件的每一行,因为一行代表一个父类
while((line = reader.readLine()) != null) {
int ci = line.indexOf(35);
if (ci >= 0) {
line = line.substring(0, ci);
}
line = line.trim();
...一行格式是: name=className,这部分代码就是把name和className解析出来 ...
//读取类信息
this.loadClass(extensionClasses, resourceURL,
Class.forName(line, true, classLoader), name, overridden);
...
}
} catch (Throwable var22) {
...
}
} finally {
...
}
} catch (Throwable var24) {
....
}
}
这里首先我们先看下strategies的来历先,strategies是通过java的spi加载进来了,得到一个数组,数组成员有:
- dubboInternalLoadingStrategy:this.directory()返回的是:
"meta-inf/dubbo/internal/"
- dubboLoadingStrategy: this.directory()返回的是:
"meta-inf/dubbo/"
- ServicesLoadingStrategy: this.directory()返回的是:
"meta-inf/services/"
所以我们读取的文件夹有meta-inf/dubbo/internal/
,meta-inf/dubbo/
,meta-inf/services/
言归正转分析loadExtensionClasses方法:
- 遍历strategies相应的文件夹,读取相应的文件(loadDirectory读取文件方法)
loadDirectory
方法:通过传进来的文件夹和类名拼接成路径字符串,然后再用类加载器去得到URL,然后调用loadResource
方法去读取文件资源loadResource
方法:读取文件中的每一行,然后再通过loadClass
去加载类。
loadClass加载类分析
ExtensionLoader类名:
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name, boolean overridden) throws NoSuchMethodException {
if (!this.type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error occurred when loading extension class (interface: " + this.type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface.");
} else {
if (clazz.isAnnotationPresent(Adaptive.class)) { //如果是类名带上@Adaptive,cachedAdaptiveClass=clazz
this.cacheAdaptiveClass(clazz, overridden);
} else if (this.isWrapperClass(clazz)) {//如果是包装类,放进包装类集合
this.cacheWrapperClass(clazz);
} else {
//确定能无参构造,确认不是包装类
clazz.getConstructor();
...name是空的情况下的处理...
//按照,分割
String[] names = NAME_SEParaTOR.split(name);
if (ArrayUtils.isNotEmpty(names)) {
this.cacheActivateClass(clazz, names[0]);
String[] var7 = names;
int var8 = names.length;
for(int var9 = 0; var9 < var8; ++var9) {
String n = var7[var9];
this.cacheName(clazz, n);
//把名字和类名put进extensionClasses
this.saveInExtensionClass(extensionClasses, clazz, n, overridden);
}
}
}
}
}
//overridden是否要覆盖
private void cacheAdaptiveClass(Class<?> clazz, boolean overridden) {
...overridden为false且原本就有cachedAdaptiveClass,就报错(一个接口不能有两个贷有Adaptive的实现类)...
this.cachedAdaptiveClass = clazz; //缓存cachedAdaptiveClass,这个就是自适应中的那个类
}
//判断是否包装类,如果构造方法是有参的认为是包装类
private boolean isWrapperClass(Class<?> clazz) {
try {
clazz.getConstructor(this.type);
return true;
} catch (NoSuchMethodException var3) {
return false;
}
}
private void cacheWrapperClass(Class<?> clazz) {
if (this.cachedWrapperClasses == null) {
this.cachedWrapperClasses = new ConcurrentHashSet();
}
this.cachedWrapperClasses.add(clazz); //放进包装类集合
}
private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name, boolean overridden) {
...overridden为false且原本就有值,就报错...
//把名字和类名put进extensionClasses
extensionClasses.put(name, clazz);
}
//把带有Activate注解的放进cachedActivates中
private void cacheActivateClass(Class<?> clazz, String name) {
Activate activate = (Activate)clazz.getAnnotation(Activate.class);
if (activate != null) {
this.cachedActivates.put(name, activate);
} else {
com.alibaba.dubbo.common.extension.Activate oldActivate = (com.alibaba.dubbo.common.extension.Activate)clazz.getAnnotation(com.alibaba.dubbo.common.extension.Activate.class);
if (oldActivate != null) {
this.cachedActivates.put(name, oldActivate);
}
}
}
loadClass流程:
-
如果类名上带有@Adaptive,存到
this.cachedAdaptiveClass
里面 -
如果类是包装类,存到
this.cachedWrapperClasses
Map集合里面 -
剩下的情况:
injectExtension依赖注入对象
//instance依赖注入的实现
private T injectExtension(T instance) {
if (this.objectFactory == null) {
return instance;
} else {
try {
//获取对象的所有方法
Method[] var2 = instance.getClass().getmethods();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
Method method = var2[var4];
//判读是否是否是以set开头的方法,且方法头上没带disableInject
if (this.isSetter(method) && method.getAnnotation(disableInject.class) == null) {
Class<?> pt = method.getParameterTypes()[0];
if (!ReflectUtils.isPrimitives(pt)) {
try {
String property = this.getSetterProperty(method);
//新建一个依赖注入的对象,pt是类名(入参第一个的类型),property指定扩展点的名字(由setXXX方法名分析而来)
Object object = this.objectFactory.getExtension(pt, property);
if (object != null) {
//给intancez注入新建的object
method.invoke(instance, object);
}
} catch (Exception var9) {
logger.error("Failed to inject via method " + method.getName() + " of interface " + this.type.getName() + ": " + var9.getMessage(), var9);
}
}
}
}
} catch (Exception var10) {
logger.error(var10.getMessage(), var10);
}
return instance;
}
}
private boolean isSetter(Method method) {
return method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers());
}
private String getSetterProperty(Method method) {
return method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
}
依赖注入实现的流程:
-
通过objectFactory.getExtension去创建一个对象
-
objectFactory是一个ExtensionFactory,里面是AdaptiveExtensionFactor。创建位置:可以看ExtensionLoader.getExtensionLoader部分
-
AdaptiveExtensionFactory.getExtension:遍历所有ExtensionFactory得实现类,然后再一个个的去尝试getExtension。其中有
SpiExtensionFactory
和SpringExtensionFactory
SpiExtensionFactory
:通过自适应扩展点去新建SpringExtensionFactory
:通过spirng容器里看下有没有这个对象有就返回
-
instance包装成包装类对象返回
这里重新看看createExtension,创建了instance并且依赖注入后,后面的逻辑
private T createExtension(String name, boolean wrap) {
...
//通过类名查看有没有缓存下来的对象
T instance = EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
//通过反射新建一个对象
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = EXTENSION_INSTANCES.get(clazz);
}
//依赖注入成员变量
this.injectExtension(instance);
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList();
//把this.cachedWrapperClasses包装类放到wrapperClassesList中并排序
if (this.cachedWrapperClasses != null) {
wrapperClassesList.addAll(this.cachedWrapperClasses);
wrapperClassesList.sort(WrapperComparator.COMParaTOR);
Collections.reverse(wrapperClassesList);
}
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
Iterator var6 = wrapperClassesList.iterator();
label37:
//遍历包装类一层层的新建包装类,
while(true) {
Class wrapperClass;
Wrapper wrapper;
do {
if (!var6.hasNext()) {
break label37;
}
wrapperClass = (Class)var6.next();
wrapper = (Wrapper)wrapperClass.getAnnotation(Wrapper.class);
} while(wrapper != null && (!ArrayUtils.contains(wrapper.matches(), name) || ArrayUtils.contains(wrapper.mismatches(), name)));
//新建包装类,把instance作为构造参数传入,让instance等于包装类
instance = this.injectExtension(wrapperClass.getConstructor(this.type).newInstance(instance));
}
}
}
this.initExtension(instance);
return instance;
}
private void initExtension(T instance) {
if (instance instanceof Lifecycle) {
Lifecycle lifecycle = (Lifecycle)instance;
lifecycle.initialize();
}
}
包装的过程:
- 把this.cachedWrapperClasses包装类集合按照相应的顺序,放到wrapperClassesList集合中
- 遍历包装类,并且一层层的包装
- 如果返回的类是Lifecycle,则调用initialize(),进行初始化
自适应扩展点解析
自定义扩展点的使用
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()
这里直接分析ExtensionLoader中的getAdaptiveExtension:
private final Holder<Object> cachedAdaptiveInstance = new Holder();
public T getAdaptiveExtension() {
Object instance = this.cachedAdaptiveInstance.get();
if (instance == null) {
...
synchronized(this.cachedAdaptiveInstance) {
instance = this.cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = this.createAdaptiveExtension();
this.cachedAdaptiveInstance.set(instance);
} catch (Throwable var5) {
this.createAdaptiveInstanceError = var5;
throw new IllegalStateException("Failed to create adaptive instance: " + var5.toString(), var5);
}
}
}
}
return instance;
}
private T createAdaptiveExtension() {
try {
return this.injectExtension(this.getAdaptiveExtensionClass().newInstance());
} catch (Exception var2) {
throw new IllegalStateException("Can't create adaptive extension " + this.type + ", cause: " + var2.getMessage(), var2);
}
}
private Class<?> getAdaptiveExtensionClass() {
this.getExtensionClasses();
return this.cachedAdaptiveClass != null ? this.cachedAdaptiveClass : (this.cachedAdaptiveClass = this.createAdaptiveExtensionClass());
}
private Class<?> createAdaptiveExtensionClass() {
String code = (new AdaptiveClassCodeGenerator(this.type, this.cachedDefaultName)).generate();
ClassLoader classLoader = findClassLoader();
Compiler compiler = (Compiler)getExtensionLoader(Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
上面的代码如下步骤:
-
判断缓冲中有没有自定义扩展点的对象,有则取出
-
执行这些步骤createAdaptiveExtension ->createAdaptiveExtension(获取相应的类返回)
-
createAdaptiveExtensionClass (从名字可以看到创建自适应扩展类)
-
this.injectExtension(this.getAdaptiveExtensionClass().newInstance())
返回getAdaptiveExtensionClass的类再通过放射新建,然后再使用依赖注入相应的成员便利。依赖注入前面也有说到 -
最后返回相应的对象,再把这个对象存到cachedAdaptiveInstance里面
拼接一个XXX$Adaptive的实现类
AdaptiveClassCodeGenerator类中的部分代码
public class AdaptiveClassCodeGenerator {
private static final Logger logger = LoggerFactory.getLogger(AdaptiveClassCodeGenerator.class);
private static final String CLASSNAME_INVOCATION = "org.apache.dubbo.rpc.Invocation";
private static final String CODE_PACKAGE = "package %s;\n";
private static final String CODE_IMPORTS = "import %s;\n";
....
public String generate() {
//遍历类的所有方法看下方法上是不是带有@Adaptive注解
if (!this.hasAdaptiveMethod()) {
throw new IllegalStateException("No adaptive method exist on extension " + this.type.getName() + ", refuse to create the adaptive class!");
} else {
StringBuilder code = new StringBuilder();
code.append(this.generatePackageInfo());
code.append(this.generateImports());
code.append(this.generateClassDeclaration());
Method[] methods = this.type.getmethods();
Method[] var3 = methods;
int var4 = methods.length;
for(int var5 = 0; var5 < var4; ++var5) {
Method method = var3[var5];
code.append(this.generateMethod(method));
}
code.append("}");
if (logger.isDebugEnabled()) {
logger.debug(code.toString());
}
return code.toString();
}
}
private String generatePackageInfo() {
return String.format("package %s;\n", this.type.getPackage().getName());
}
//遍历类的所有方法看下方法上是不是带有@Adaptive注解
private boolean hasAdaptiveMethod() {
return Arrays.stream(this.type.getmethods()).anyMatch((m) -> {
return m.isAnnotationPresent(Adaptive.class);
});
}
}
可以看到首先要先看下类的方法上是否带了@Adaptive注解 ,有的话会把一个类文件的内容拼接成字符串返回。
如果是ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()
最后生成的类如下:
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {
throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
//从Invoker中获取URL
org.apache.dubbo.common.URL url = arg0.getUrl();
//如果为空则返回dubbo协议,然后再通过名字的扩展点,找到相应的protocol对象
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
//调用指定名字扩展点得到的对象进行方法调用
return extension.export(arg0);
}
public java.util.List getServers() {
throw new UnsupportedOperationException("The method public default java.util.List org.apache.dubbo.rpc.Protocol.getServers() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public org.apache.dubbo.rpc.Invoker refer(java.lang.class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
if (arg1 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);
}
}
可以看到最后生成的类其实就是:
激活扩展点解析
回顾一下怎么使用:
测试类