dubbo spi源码
2022-06-02 10:17:49 0 举报
dubbo spi机制的源码流程图
作者其他创作
大纲/内容
clazz.getConstructor()
injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance))
子流程
urls一个接口引入的实现类只能由一个@Adaptive注解的类?@Adaptive写在接口方法?一个type只会有一个ExtensionLoader实例wrapperclass测试factoriestreeset有序性测试
getAdaptiveExtensionClass()
Class<?> clazz = getExtensionClasses().get(name)
拿到接口的代理类型
这两种情况是不会添加到extensionClasses中的
扩展点对象
injectExtension(instance)
需要有无参构造方法否则会报错
拿到注入对象,如果对象不为null则就去执行set方法注入
是
找当前type接口类型的所有扩展类如果当前type接口对应的ExtensionLoader对象中cachedAdaptiveClass缓存(解析spi文件获取所有扩展类的时候就会将@Adaptive注解的类缓存起来)中没有数据那么就去自动用代码去生成一个类
createExtension(name)创建扩展点对象
没有
loader.getAdaptiveExtension()
@SPI(\"default\") // 如果这里没有默认的值,那么getExtension(\"true\")返回nullpublic interface A{}当getExtension(\"true\") -> getDefaultExtension() -> getExtension(\"default\")
加载类,并添加到extensionClasses中
cachedAdaptiveInstance缓存中有就拿缓存中的数据,没有就去创建
name=\"true\"
set方法注入
name: clazz添加到extensionClasses中不同的name可以对上相同的实现类一个name如果有多个不同的实现类会报错
这里用Holder包装也是为了解决并发问题
这个WrapperClass是在解析spi文件的时候就缓存好的。遍历cachedWrapperClasses,有几个WrapperClass就包装几层,每包装一层这个包装类都需要去依赖注入的
拿到接口所有的扩展实现类
false
spi文件中name对应的实现类
有符合的扩展点类型
遍历,只要从某个ExtensionFactory中获取到对象实例就return
得到setXxx中的xxx
loadExtensionClasses()
缓存一下被Activate注解了的类key: names[0]value: @Activate
getExtensionClasses
ExtensionLoader.getExtensionLoader(Class type)type为接口且有@SPI注解否则会报错
publicmethodname starts with \"set\"only has one parameter方法没有@DisableInject注解方法仅有的参数类型不是简单类型,如果是array类型的话,元素类型不是简单类型
clazz有没有@Adaptive
拿到name对应的扩展点实现类
一个接口引入的实现类只能有一个类是有@Adaptive注解否则会报错
@SPI注解的该接口必须要至少有一个@Adaptive注解的方法,否则直接抛错。这个自动生成代码流程就不画了,主要看下generateMethod()方法的generateMethodContent(method)要点: - @SPI注解的接口的方法如果没有@Adaptive注解则生成代理对象的该方法是直接throw exception,调用就会抛错 - 如果接口的方法没有URL参数 -> 去遍历方法中的每个参数,遍历每个参数类型中的get方法,如get方法的返回类型为URL,如果最终没有找到URL那么就直接会报错了
1. 在文件中没有name,但是在类上指定了Extension的注解上指定了name2. 文件中没有name类上没有@Extension注解 - BlackCar ---> black - BlackCar123 ---> blackcar123
依赖注入
extensionLoader.getExtension(String name)
cacheWrapperClass(clazz)
是不是WrapperClass
String[] names = NAME_SEPARATOR.split(name)
findClassLoader()找类加载器
findAnnotationName(clazz)
拿到spi文件中所有的扩展实现类name : 实现类
SpringExtensionFactory
ExtensionLoader<Person> extensionLoader = ExtensionLoader.getExtensionLoader(Person.class); Person person = extensionLoader.getExtension(\"black\");
返回注入对象
子流程加载资源文件填充Map
子流程objectFactory实例AdaptiveExtensionFactory
三种类加载器1. bootstrap - 加载路径:jre/lib2. ext - 加载路径:jre/ext/lib3. app - 加载路径:classpath,java应用启动的时候日志台打印可以去看
String property = getSetterProperty(method)
缓存实例对象实现类 : 实现类实例对象
cacheDefaultExtensionName()拿默认的接口扩展类
createAdaptiveExtensionClass()
有
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type)
不是
代码自动创建一个代理对象
很明显这里又要去给这个注入的对象去进行set方法的属性赋值
getSupportedExtensions
cacheAdaptiveClass(clazz)缓存该clazz
BufferedReader遍历读取spi文件每一行拿到name和clazz
获取注入对象
接口有@Adaptive注解的类那么就用这了类的实例对象,没有则用代码生成一个接口的代理对象
缓存该wrapperclassclazz.getConstructor(type)不报错也就是说要有个构造函数 - 参数类型为接口类型type且只有一个参数
name有没有值
如果有Wrapper类的话,会将这个instance包装一层Wrapper
injectExtension((T) getAdaptiveExtensionClass().newInstance())给代理对象set注入
SpiExtensionFactory
加载SPI配置文件,将符合的扩展点类型添加到extensionClasses
入口
set方法注入的类型是接口且接口上有@SPI注解,否则return null走下一个ExtensionFactory
createAdaptiveExtension()
0 条评论
下一页