网站建设与管理好学吗,专门做任务的网站吗,100款软件app免费下载大全,崇信门户网站留言回复文章目录 Dubbo SPI使用方式AOP功能源码剖析SPI注解1.获取加载器2.获取拓展实例对象3.创建拓展类的实例对象 Dubbo SPI Dubbo 的 SPI#xff08;Service Provider Interface#xff09;机制是一种强大的扩展机制#xff0c;它允许开发者在运行时动态地替换或增加框架的功能。… 文章目录 Dubbo SPI使用方式AOP功能源码剖析SPI注解1.获取加载器2.获取拓展实例对象3.创建拓展类的实例对象 Dubbo SPI Dubbo 的 SPIService Provider Interface机制是一种强大的扩展机制它允许开发者在运行时动态地替换或增加框架的功能。Dubbo 的 SPI 机制与 Java 原生的 SPI 机制有所不同它提供了更多的灵活性和功能。 SPI机制的核心组件包括 服务接口接口定义了服务提供者需要实现的方法应用程序将使用这个接口与具体的服务实现进行交互。 服务实现这是实现了服务接口的具体类第三方可以为服务接口提供多个实现。 服务提供者配置文件这是一个位于META-INF/dubbo目录下的文件文件名与服务接口的全限定名相同该文件包含了服务实现类的全限定名每行一个接口的具体实现类在运行时就可以加载这些实现类。 ServiceLoader用于加载服务实现应用程序可以使用ServiceLoader来获取服务接口的所有具体实现类。
SPI的工作流程如下
定义服务接口。实现服务接口创建具体的服务实现类。在META-INF/dubbo目录下创建服务提供者配置文件列出所有服务实现类的全限定名。使用ServiceLoader加载服务具体实现类并根据需要使用它们。
总结就是说SPI机制使得应用程序可以在运行时动态地选择和加载服务实现从而提高了应用程序的可扩展性和灵活性。
使用方式
使用方式和 java的SPI类似首先通过SPI注解定义服务接口
SPI
public interface Greeting {public void sayHello();
}
再定义服务实现类实现接口并重写接口中的方法
public class ChineseGreeting implements Greeting {Overridepublic void sayHello() {System.out.println(你好世界!);}
}public class EnglishGreeting implements Greeting {Overridepublic void sayHello() {System.out.println(Hello World!);}
}在META-INF/dubbo目录下创建一个名为com.xydp.dubbo.Greeting的文件用于存储自定义键名这里与java的 SPI 不同需要自定义key的名称键名随意主要是为了实现后面按需加载与具体实现类的全限定名。文件内容如下 文件内容
englishcom.xydp.dubbo.EnglishGreeting
chinesecom.xydp.dubbo.ChineseGreeting编写测试类
public class SpiDemo {public static void main(String[] args) {ExtensionLoaderGreeting extensionLoader ExtensionLoader.getExtensionLoader(Greeting.class);Greeting englishGreeting extensionLoader.getExtension(english);englishGreeting.sayHello();System.out.println(englishGreeting.getClass());}
}输出结果 Dubbo的 SPI 通过自定义键名的方式按需加载可以在O(1)的时间复杂度获取具体的服务实现类而java SPI 需要通过迭代器的方式全局遍历获取某个具体实现类达到线性时间复杂度O(n)。
Dubbo SPI与Java SPI区别 设计理念Java SPI 主要关注于服务实现的加载而 Dubbo SPI 更注重于框架的可扩展性和灵活性。 功能丰富度Dubbo SPI 提供了更多的功能如自适应扩展、激活扩展和依赖注入等而 Java SPI 功能相对有限。 加载方式Java SPI 采用全局加载的方式加载特定的实现类时间复杂度达到O(n)性能差而 Dubbo SPI 采用按需加载的方式时间复杂度只需O(1),提高了性能。 配置方式Dubbo SPI 支持通过注解和 URL 参数进行动态配置使得框架更加灵活Java SPI 主要通过配置文件进行静态配置。
总之Java SPI 和 Dubbo SPI 都是用于实现服务发现和实现加载的机制但 Dubbo SPI 在设计理念、功能和用法上更加灵活和强大Dubbo SPI 更适合用于构建复杂的分布式系统而 Java SPI 更适合用于简单的服务加载场景。
AOP功能
在 Dubbo 中实现 AOP 功能的方式是通过自定义 Wrapper 类实现的Dubbo 要求实现 AOP 功能的类以 Wrapper 结尾这是一种约定以便于识别这些类是用于包装服务实现的Wrapper 类是 Dubbo 框架的一部分用于在运行时动态地为服务实现类添加额外的功能原理和Spring AOP类似将通知织入所要执行的目标方法前后。
public class GreetingWrapper1 implements Greeting{private Greeting greeting;public GreetingWrapper1(Greeting greeting){this.greeting greeting;}Overridepublic void sayHello() {System.out.println(before do someting);this.greeting.sayHello();System.out.println(after do something);}
}同时需要在配置文件中添加包装类的全限定名
测试类保持不变
public class SpiDemo {public static void main(String[] args) {ExtensionLoaderGreeting extensionLoader ExtensionLoader.getExtensionLoader(Greeting.class);Greeting englishGreeting extensionLoader.getExtension(english);englishGreeting.sayHello();System.out.println(englishGreeting.getClass());}
}输出结果
从结果可以看出最终执行的是GreetingWrapper1中greeting的sayHello()方法GreetingWrapper1在这里充当EnglishGreeting的代理对象。
源码剖析
SPI注解
在 Dubbo 的 SPI 机制中SPI 注解用于标记一个接口为可扩展的扩展点SPI 注解有两个可选参数value 和 scope。
Documented
Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE})
public interface SPI {String value() default ;ExtensionScope scope() default ExtensionScope.APPLICATION;
}value 参数用于指定扩展点的默认实现类当没有其他扩展实现类被明确指定时Dubbo 会使用 value 参数指定的key表示从配置文件中查找对应的实现类。 scope 参数指定扩展实现类的作用域有以下四种作用域 Constants.FRAMEWORK框架作用域在Dubbo框架内实现类只会生成唯一实例并在整个应用程序内共享。 Constants.APPLICATION应用程序作用域在应用程序上下文中实现类仅会被实例化一次并在整个应用程序中共享是默认的作用域。 Constants.MODULE模块作用域在模块上下文中该实现类将仅创建一个实例并在该模块内共享。 Constants.SELF自定义作用域用户可定义实现类的作用范围涵盖任意范围。
1.获取加载器
当执行获取拓展加载器这行代码时 ExtensionLoaderGreeting extensionLoader ExtensionLoader.getExtensionLoader(Greeting.class);源码如下
public T ExtensionLoaderT getExtensionLoader(ClassT type) {//检查拓展目录是否被删除this.checkDestroyed();//校验类型是否为nullif (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 {//如果类型不为null,尝试从缓存中获取加载器loader以及作用域ExtensionLoaderT loader (ExtensionLoader)this.extensionLoadersMap.get(type);ExtensionScope scope (ExtensionScope)this.extensionScopeMap.get(type);//如果缓存中不存在scope,就从SPI注解获取scope,再放入缓存if (scope null) {SPI annotation (SPI)type.getAnnotation(SPI.class);scope annotation.scope();this.extensionScopeMap.put(type, scope);}//如果加载器为null且作用域是SELF,就直接创建loaderif (loader null scope ExtensionScope.SELF) {loader this.createExtensionLoader0(type);}//若lader为空作用域不是SELF且父类加载器不为空那么尝试从父类加载器去获取loaderif (loader null this.parent ! null) {loader this.parent.getExtensionLoader(type);}//若无法从父类加载器获取loader那么自己实例化一个loader并放入缓存if (loader null) {loader this.createExtensionLoader(type);}//返回加载器return loader;}}private T ExtensionLoaderT createExtensionLoader(ClassT type) {ExtensionLoaderT loader null;//根据SPI注解的属性判断作用域是否等于默认作用域if (this.isScopeMatched(type)) {loader this.createExtensionLoader0(type);}return loader;}private T ExtensionLoaderT createExtensionLoader0(ClassT type) {//检查拓展目录是否被删除this.checkDestroyed();//根据类型创建加载器并放入缓存this.extensionLoadersMap.putIfAbsent(type, new ExtensionLoader(type, this, this.scopeModel));//从缓存获取loaderExtensionLoaderT loader (ExtensionLoader)this.extensionLoadersMap.get(type);//返回loaderreturn loader;}2.获取拓展实例对象
执行这行代码获取拓展类的实例对象
Greeting englishGreeting extensionLoader.getExtension(english);源码如下 public T getExtension(String name) {//获取拓展实例对象T extension this.getExtension(name, true);if (extension null) {throw new IllegalArgumentException(Not find extension: name);} else {//获取到了返回return extension;}}public T getExtension(String name, boolean wrap) {//检查拓展目录是否被删除this.checkDestroyed();//若参数为空抛异常if (StringUtils.isEmpty(name)) {throw new IllegalArgumentException(Extension name null);}//若拓展类名称为true,表示使用SPI注解中声明的默认拓展实现类 else if (true.equals(name)) {return this.getDefaultExtension();} else {String cacheKey name;if (!wrap) {cacheKey name _origin;}//尝试从缓存中获取拓展类实例对象如果获取不到cacheKey对应的holder//则会创建一个空的holder再返回HolderObject holder this.getOrCreateHolder(cacheKey);Object instance holder.get();//若获取不到则采用双重检验的单例模式创建实例对象代码第一次执行是获取不到对象的//此时instance为null//第一层判断是为了提高执行速度防止实例对象不为空时还去竞争锁if (instance null) {synchronized(holder) {instance holder.get();//第二层判断是为了避免创建重复的实例对象if (instance null) {//获取拓展类实例对象instance this.createExtension(name, wrap);//将实例对象放入缓存holder.set(instance);}}}//返回实例对象return instance;}}private HolderObject getOrCreateHolder(String name) {//根据推展类名称获取缓存对象holderHolderObject holder (Holder)this.cachedInstances.get(name);//获取不到则创建一个空的holder并放入缓存if (holder null) {this.cachedInstances.putIfAbsent(name, new Holder());holder (Holder)this.cachedInstances.get(name);}//返回holderreturn holder;}Holder类是一个缓存对象用于缓存自定义键名对应的拓展类实例对象
public class HolderT {
//volatil的作用是禁止指令重排序private volatile T value;public Holder() {}public void set(T value) {this.value value;}public T get() {return this.value;}
}
可以看到缓存Holder类用volatile修饰变量这样做是为了禁止指令重排序避免返回一个未初始化完成的实例对象创建一个对象分为3步
为对象分配内存空间初始化对象将对象指向1所分配的内存空间
若holder没有用volatile修饰2和3的指令发生顺序颠倒此时指令的执行顺序为1-3-2,当执行完3时代码执行到第二层 if 判断发现instance不为null,此时直接返回instance,返回的是还未初始化的对象(对象的属性未赋值)。
3.创建拓展类的实例对象
第一次执行时缓存是获取不到实例对象的所以需要创建之后就能从缓存中直接获取。 private T createExtension(String name, boolean wrap) {//解析配置文件先获取所有的拓展类再根据类名获取对应的classClass? clazz (Class)this.getExtensionClasses().get(name);if (clazz ! null !this.unacceptableExceptions.contains(name)) {try {//根据类对象从缓存获取类实例对象T instance this.extensionInstances.get(clazz);//获取不到则通过反射的方式创建实例对象并放入缓存if (instance null) {this.extensionInstances.putIfAbsent(clazz, this.createExtensionInstance(clazz));instance this.extensionInstances.get(clazz);//前置处理instance this.postProcessBeforeInitialization(instance, name);//依赖注入this.injectExtension(instance);//后置处理instance this.postProcessAfterInitialization(instance, name);}//包装类的处理用于实现AOP功能if (wrap) {ListClass? wrapperClassesList new ArrayList();if (this.cachedWrapperClasses ! null) {wrapperClassesList.addAll(this.cachedWrapperClasses);wrapperClassesList.sort(WrapperComparator.COMPARATOR);Collections.reverse(wrapperClassesList);}if (CollectionUtils.isNotEmpty(wrapperClassesList)) {Iterator var6 wrapperClassesList.iterator();while(var6.hasNext()) {Class? wrapperClass (Class)var6.next();Wrapper wrapper (Wrapper)wrapperClass.getAnnotation(Wrapper.class);boolean match wrapper null || (ArrayUtils.isEmpty(wrapper.matches()) || ArrayUtils.contains(wrapper.matches(), name)) !ArrayUtils.contains(wrapper.mismatches(), name);if (match) {instance this.injectExtension(wrapperClass.getConstructor(this.type).newInstance(instance));instance this.postProcessAfterInitialization(instance, name);}}}}//生命周期管理this.initExtension(instance);return instance;} catch (Throwable var10) {throw new IllegalStateException(Extension instance (name: name , class: this.type ) couldnt be instantiated: var10.getMessage(), var10);}} else {throw this.findException(name);}}1)解析配置文件获取拓展类 private MapString, Class? getExtensionClasses() {//从缓存中获取拓展类MapString, Class? classes (Map)this.cachedClasses.get();//缓存获取不到通过双重检查锁的单例模式创建拓展类if (classes null) {synchronized(this.cachedClasses) {classes (Map)this.cachedClasses.get();if (classes null) {try {//解析配置文件获取类信息并放入缓存classes this.loadExtensionClasses();} catch (InterruptedException var5) {logger.error(0-15, , , Exception occurred when loading extension class (interface: this.type ), var5);throw new IllegalStateException(Exception occurred when loading extension class (interface: this.type ), var5);}this.cachedClasses.set(classes);}}}return classes;}private MapString, Class? loadExtensionClasses() throws InterruptedException {//检查拓展目录是否被销毁this.checkDestroyed();//判断SPI注解中的默认参数是否合法this.cacheDefaultExtensionName();MapString, Class? extensionClasses new HashMap();LoadingStrategy[] var2 strategies;int var3 var2.length;//解析三个配置文件的信息并将类信息放入缓存//三个配置文件 META-INF/dubbo/,META-INF/dubbo/internal/,META-INF/services/for(int var4 0; var4 var3; var4) {LoadingStrategy strategy var2[var4];this.loadDirectory(extensionClasses, strategy, this.type.getName());if (this.type ExtensionInjector.class) {this.loadDirectory(extensionClasses, strategy, ExtensionFactory.class.getName());}}return extensionClasses;}(2)实例化对象 T instance this.extensionInstances.get(clazz);if (instance null) {this.extensionInstances.putIfAbsent(clazz, this.createExtensionInstance(clazz));instance this.extensionInstances.get(clazz);}//通过反射的方式创建实例对象private Object createExtensionInstance(Class? type) throws ReflectiveOperationException {return this.instantiationStrategy.instantiate(type);}(3)前置处理 前置处理和Spring的前置处理类似可以在实例对象初始化之前执行一些自定义的初始化逻辑例如检查实例对象是否满足某些条件或者为实例对象添加一些额外的功能。
instance this.postProcessBeforeInitialization(instance, name);private T postProcessBeforeInitialization(T instance, String name) throws Exception {ExtensionPostProcessor processor;if (this.extensionPostProcessors ! null) {for(Iterator var3 this.extensionPostProcessors.iterator(); var3.hasNext(); instance processor.postProcessBeforeInitialization(instance, name)) {processor (ExtensionPostProcessor)var3.next();}}return instance;}(4)依赖注入 Dubbo的依赖注入只支持Setter方法级别的注入。
this.injectExtension(instance);private T injectExtension(T instance) {if (this.injector 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];//方法是setter方法方法不包含DisableInject注解且instance不是基本数据类型if (this.isSetter(method) !method.isAnnotationPresent(DisableInject.class) method.getDeclaringClass() ! ScopeModelAware.class (!(instance instanceof ScopeModelAware) !(instance instanceof ExtensionAccessorAware) || !ignoredInjectMethodsDesc.contains(ReflectUtils.getDesc(method)))) {//获取方法的参数类型Class? pt method.getParameterTypes()[0];if (!ReflectUtils.isPrimitives(pt)) {try {//获取参数值String property this.getSetterProperty(method);//根据参数类型和参数值获取依赖对象Object object this.injector.getInstance(pt, property);if (object ! null) {//将依赖对象object注入instancemethod.invoke(instance, object);}} catch (Exception var9) {logger.error(0-15, , , Failed to inject via method method.getName() of interface this.type.getName() : var9.getMessage(), var9);}}}}} catch (Exception var10) {logger.error(0-15, , , var10.getMessage(), var10);}return instance;}}(5)后置处理 后置处理的思想与Spring的后置处理类似。 instance this.postProcessAfterInitialization(instance, name);private T postProcessAfterInitialization(T instance, String name) throws Exception {if (instance instanceof ExtensionAccessorAware) {((ExtensionAccessorAware)instance).setExtensionAccessor(this.extensionDirector);}ExtensionPostProcessor processor;if (this.extensionPostProcessors ! null) {for(Iterator var3 this.extensionPostProcessors.iterator(); var3.hasNext(); instance processor.postProcessAfterInitialization(instance, name)) {processor (ExtensionPostProcessor)var3.next();}}return instance;}(6)包装类Wrapper处理 Dubbo的AOP功能就是通过Wrapper实现的。 if (wrap) {ListClass? wrapperClassesList new ArrayList();//判断wrapper缓存包装类集合是否为空// 不为空则加入list集合中然后排序之后再翻转if (this.cachedWrapperClasses ! null) {wrapperClassesList.addAll(this.cachedWrapperClasses);wrapperClassesList.sort(WrapperComparator.COMPARATOR);Collections.reverse(wrapperClassesList);}//判断wrapper包装类集合不为空if (CollectionUtils.isNotEmpty(wrapperClassesList)) {Iterator var6 wrapperClassesList.iterator();//遍历集合中的每一个包装类while(var6.hasNext()) {Class? wrapperClass (Class)var6.next();//获取包装类的注解Wrapper wrapper (Wrapper)wrapperClass.getAnnotation(Wrapper.class);//判断是否符合包装条件boolean match wrapper null || (ArrayUtils.isEmpty(wrapper.matches()) || ArrayUtils.contains(wrapper.matches(), name)) !ArrayUtils.contains(wrapper.mismatches(), name);//符合包装条件将当前实例对象添加到包装类中并做一些后置处理if (match) {//将instance作为参数传给wrapper的构造方法通过反射的方式创建wrapper实例//再往wrapper实例注入依赖然后将wrapper赋值给instance,再对instance做后置处理instance this.injectExtension(wrapperClass.getConstructor(this.type).newInstance(instance));instance this.postProcessAfterInitialization(instance, name);}}}}(7)生命周期管理 this.initExtension(instance);private void initExtension(T instance) {if (instance instanceof Lifecycle) {Lifecycle lifecycle (Lifecycle)instance;lifecycle.initialize();}}