「spijava注解」java的spi
今天给各位分享spijava注解的知识,其中也会对java的spi进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、基于spring factories机制开发SDK
- 2、Dubbo SPI之Adaptive详解
- 3、SpringBoot自动配置/装配(SPI)
- 4、java的API中有哪些常用的包?
- 5、请问一个关于java中的spit的用法
- 6、SPI用法简介
基于spring factories机制开发SDK
SPI机制:为某个接口寻找服务实现的机制
java SPI就是提供这样的一个机制 ,需要在META-INF目录中设置接口的实现,以实现服务接口与实现的解耦。第三方服务厂商或者插件服务,可以依据SPI机制,实现功能扩展。
在Spring中也有一种类似与Java SPI的加载机制。它在META-INF/spring.factories文件中配置接口的实现类,我们成为Spring factories机制,基于此我们可以自定义stater或SDK供他人使用,项目只在pom.xml中引入SDK,无须配置即可实现功能集成。
最近的需求为例,需要实现授权功能SDK,以供其他产品使用
项目目录结构如下
第一步:在包名root目录下创建自动配置类 EsbrSdkAutoConfig
内容如下:添加
@Configuration
@ComponentScan(basePackageClasses = EsbrSdkAutoConfig.class)
标识此类为配置类,并配置扫描路径为当前类
第二步; 在resources/META-IN目录下,创建spring.factories文件
内容如下:
将org.springframework.boot.autoconfigure.EnableAutoConfiguration的自动配置为值设置为第一步的EsbrSdkAutoConfig的全限定类名(包名+类名)
第三步:编写SDK的Service
通过以上三步,即可基于Spring factories机制完成自定义Starter,在其他项目pom.xml中引入该starter即可
是不是很简单,下面讲解下原理
spring-core包里定义了SpringFactoriesLoader类,这个类实现了检索META-INF/spring.factories文件中的配置,
并通过 loadFactoryNames方法() 获取其接口类的名称
在这个方法中会遍历整个ClassLoader中所有jar包下的spring.factories文件。也就是说我们可以在自己的jar中配置spring.factories文件,不会影响到其它地方的配置,也不会被别人的配置覆盖。
将org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.org.bjca.esbr.sdk.EsbrSdkAutoConfig
基于springboot自动配置,会扫描并初始化EsbrSdkAutoConfig类,并将EsbrSdkAutoConfig作为basepackage,扫描改类及其该类子包下的类,加载到spring容器。
Dubbo SPI之Adaptive详解
为ThriftAdaptiveExt2类添加@Adaptive注解
下面我们带着上面的结论,看一下源码。首先我们从这句话开始讲起
下面是源码的注释
先检查有没有带SPI的注解,没有带,直接报错,从缓存中根据这个类型查询对应的ExtensionLoader,查不到就创建一个,再放入缓存中。dubbo中的spi部分大量利用了本地缓存,后续出现,不再着重讲解了。我们可以看一下他的创建该类型的ExtensionLoader的方法。
关注点有两个,第一个构造方法是私有的,说明不想通过外部实例化,将实例化的过程统一收紧。第二个是objectFactory这个在后面的ioc部分会发挥它的作用,敬请期待。好了,目前为止,ExtensionLoaderAdaptiveExt2 loader = ExtensionLoader.getExtensionLoader(AdaptiveExt2.class) 说的差不多了,下面进入我们的大头getAdaptiveExtension
第一次从缓存中获取就创建
获取到适配器类的Class,利用反射创建适配器类的实例。injectExtension是dubbo的DI,依赖注入。如果适配器类有属性的set方法,会自动注入,这个后续会开一个章节进行解释。看来我们最终要关注的是getAdaptiveExtensionClass方法。大家跟紧了,大片开始了。
按照顺序来吧,看下getExtensionClasses
从缓存中取,也就是说,加载的流程只触发一次,然后放入缓存,后续从缓存取。
获取type上的SPI注解,如果里面有值赋给cachedDefaultName这个变量,相当于是个默认的值。随后从META-INF/dubbo/internal/,META-INF/dubbo/,META-INF/services/这三个路径下搜索对应的文件,什么是对应的?就是命名是这个type类的全限定名称。下面这个方法有点长,希望不要看吐,还好加了注解,希望看起来会通畅点。
路径+文件名,组成了一个具体的文件名,根据 classLoader.getResources 方法获取到Enumerationjava.net.URL 类型的对象,随后就是遍历,文件里面的格式是这样的。
如果有 # ,按照 # 分割,前面的是我们需要的业务数据,后面是注释。我们所需要的数据中如果有 = ,那么就按照 = 进行分割,前面是这个扩展的名称,后面是这个扩展的全限定类名,方便利用反射加载进来。加载进来之后会判断下是不是传入类(type)类型的实例,不是的话,报错!如果有的类上带有@Adaptive注解,那么将这个类赋值给cachedAdaptiveClass,注意这个点,查询type类型适配器类的时候会优先寻找cachedAdaptiveClass,因为是系统指定的适配器类,优先级最高,可以看下我们上面的测试三,说的就是这种情况。如果有多个实现再类上都打上了@Adaptive注解,会报错:标准的适配器类只能有一个。如果这个扩展类没有打上@Adaptive注解就更有意思了。首先第一步会验证下有没有type这个类型作为入参的构造方法,为什么要这么做?因为Wrapper,有的类型需要包装一下,例如type=Protocol.class 就会看到有DubboProtocol真实的Protocal类,还会有ProtocolFilterWrapper和ProtocolListenerWrapper这种Wrapper类,这种Wrapper类的共同点就是构造函数的入参是type类型,所以在解析的时候有这么一步。如果有这种构造函数的就是Warpper类,将这些Warpper类型的数据放到cachedWrapperClasses这个集合中缓存。如果没有这种类型的构造函数,就是正常的type类型的实例了,如果在文件中没有声明这个扩展的名称( = 左边的部分),就会根据这个类名创建一个名称。然后进入下一个环节@Activate数据的解析,这个本来是下一节的内容,我们提前了解下吧。查看type类上有没有@Activate注解,如果有的话,将名称与注解放到cachedActivates这个Map中进行缓存。将扩展类和名称放入cachedNames这个Map中进行缓存,将名称和扩展类的class放入传递进来的extensionClasses中,最后这个extensionClasses会被返回出来被使用。OK,到目前为止我们结束了getExtensionClasses方法的讲解,是不是很绕,东西很多。再回来我们看下剩下的。
如果cachedAdaptiveClass不为空就返回,什么情况下不为空?当扩展类上打上@Adaptive注解的时候,就会将这个类直接返回。如果没有上注解,怎么办,就得自己生成了,也就是createAdaptiveExtensionClass
思路很简单,将类以字符串的形式拼接出来,然后利用编译器进行编译,返回编译后的class对象。寻找编译器的过程和具体编译的过程不是我们此次所要关心的,我们关心的是这个createAdaptiveExtensionClassCode方法创建的字符串格式的数据是啥样的,用到了哪些数据。又是一个大方法,也是要走起的,come on
首先寻找这个类中所有的方法,查看方法中有没有打@Adaptive注解的,一个没有,直接报错!对于那些没有加@Adaptive注解的方法,直接在要创建的Adaptive类上增加此方法不支持操作的异常。在方法中的@Adaptive是可以加上value值的,如果用户填了,使用此值,没有填将使用程序根据类名创建的值作为value值,这个value值通URL中的参数名保持一致。defaultExtName是SPI中的value值,这里可以看一下我们的测试四的方法。最后我们看一下,他生成的String是什么样子的
将上面这个字符串编译成Class对象,作为适配器类,返回,然后实例化后,进行依赖注入需要的属性,随后缓存,备下次使用。
基本上所有类型的动态导入都是使用adaptive,使用范围极广。
dubbo-test测试源码
下一篇: Dubbo SPI 之Activate详解
END
SpringBoot自动配置/装配(SPI)
自己动手写一个启动器的经历:
这里报错了,原因是只导入了一个bean而SpringBoot无法启动服务器
解决办法一:将@Import改成@ConponentScan这样就会扫描同级包和子包。
解决办法二:关闭web服务器
自动装配的大概流程 :@EnableAutoConfiguration目的是自动装配在Maven中的第三方依赖,然后通过@Import(seleter)导入selecter,再通过selecter找到对应的.factories文件最终加载了打上@Configuration的文件。
首先开启了自动装配
通过Selector方法返回对应的类的名字
SPI全名为Service Provider Interface
模块 实现方案
| | | | | | | 方案A
调用方 标准服务接口 方案B
| | | | | | | 方案C
基于interface + 策略模式 + 配置模式
整体解决方案的变化
与@Primary@条件注解的区别:具体/粒度小。
java的API中有哪些常用的包?
Application Programming Interface 应用程序编程接口,Java的api就多的数不清了,平时编程用的都是API。
请问一个关于java中的spit的用法
str[0]="";
如果你要判断的话用这个式子保险
if(str[0] != null str[0].length() != 0){
;}
在eclipse里面试一下啊,有debug选项在spit后面设置断点,然后进入debug,到变量空间里面看看即可!
SPI用法简介
spi是Service Provider Interface的缩写。使用spi技术可以通过修改配置的方式,更换程序中某个接口的实现类,从而改变程序行为。spi的用法如下:
建立文件META-INF\services\com.foo.bar.service.FooService,写入下面两行:
编辑文件META-INF/services/java.sql.Driver,加入所需要的驱动类。
参考资料
关于spijava注解和java的spi的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-11-23,除非注明,否则均为
原创文章,转载请注明出处。