关于Java SPI

SPI:Service Provider Interface

自身只定义接口,通过其他jar来提供实现,从而可以实现jar包替换后即可执行,实现IoC,可用于plugins/modules。

[b](1)Java Service Loader[/b]

[b]JDK 6开始提供java.util.ServiceLoader[/b]

[url=https://docs.oracle.com/javase/tutorial/ext/basics/spi.html]https://docs.oracle.com/javase/tutorial/ext/basics/spi.html[/url]
[url=https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html]https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html[/url]

定义实现类
[color=blue]META-INF/services/[InterfaceFQCN] [/color]

比如:
META-INF/services/com.rensanning.spi.Sample
[quote]com.rensanning.spi.SampleImpl1 # comment1
com.rensanning.spi.SampleImpl2 # comment2[/quote]

-可以定义多行,一行一个实现(多个实现具体如何用是在程序内部控制的)
-#号开头的是注释
-必须UTF-8编码(避免使用非英语字符)

获取实现类
ServiceLoader<Sample> loader = ServiceLoader.load(Sample.class);
for (Sample provider: loader) {
// ...
}


-默认采用的是当前线程的类加载器(Thread Context Classloader)
-可以自己指定类加载器:ServiceLoader.load(Sample.class, ClassLoader.getSystemClassLoader());
-ServiceLoader只能通过无参构造函数对服务实例
-ServiceLoader返回一个Iterator对象对服务实例懒加载,只有调用next()方法时才会实例化下一个服务实例

集成Spring
@Configuration
public class ServiceConfiguration {
@Bean
public ServiceListFactoryBean serviceListFactoryBean() {
ServiceListFactoryBean serviceListFactoryBean = new ServiceListFactoryBean();
serviceListFactoryBean.setServiceType(Sample.class);
return serviceListFactoryBean;
}
}

Object object = serviceListFactoryBean.getObject();


JDK1.5通过sun.misc.Service(未公开的API)来加载。

Iterator<Sample> i = Service.providers(Sample.class);
while (i.hasNext()) {
Sample s = i.next();
// ...
}


-其实META-INF/services是JDK 1.3开始就有的“Java Extension Mechanism”

[b]最典型的2个应用:JDBC、Logger[/b]

[b]JDBC[/b]

JDBC4 定义了接口java.sql.Driver,具体实现可以是MySQL、PostgreSQL等
mysql-connector-java-5.1.22-bin.jar/META-INF/services/java.sql.Driver
[quote]com.mysql.jdbc.Driver[/quote]
postgresql-9.4-1201-jdbc4.jar/META-INF/services/java.sql.Driver
[quote]org.postgresql.Driver[/quote]

java.sql.DriverManager在初始化的时候会主动加载这些驱动类,不需要Class.forName()。
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);


[b]Logger [/b]

可以通过实现来切换JUL,Logback, Log4J等

SLF4J 定义了接口org.slf4j.Logger,但还不支持SPI,仍采用的是StaticLoggerBinder来实现的。
[url=https://jira.qos.ch/browse/SLF4J-227]https://jira.qos.ch/browse/SLF4J-227[/url]

JBoss Logging:META-INF/services/org.jboss.logging.LoggerProvider
common-logging:META-INF/services/org.apache.commons.logging.LogFactory

[color=red]OSGi 和 SPI之间还有些纠纷,具体可以看看这里:[/color]
[url=http://blog.osgi.org/2013/02/javautilserviceloader-in-osgi.html]http://blog.osgi.org/2013/02/javautilserviceloader-in-osgi.html[/url]

[b](2)Spring Factories Loader[/b]
Spring自己实现了一个类似于属性文件的配置文件:[color=blue]META-INF/spring.factories[/color]

[url=http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/SpringFactoriesLoader.html]http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/support/SpringFactoriesLoader.html[/url]
[url=http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/serviceloader/package-summary.html]http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/serviceloader/package-summary.html[/url]

比如:
spring-boot-autoconfigure-1.5.2.RELEASE.jar/META-INF/spring.factories
[quote]# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider[/quote]

org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders
List<TemplateAvailabilityProvider> providers = SpringFactoriesLoader.loadFactories(TemplateAvailabilityProvider.class, classLoader);


参考:
https://dzone.com/articles/java-service-loader-vs-spring-factories-loader
http://stackoverflow.com/questions/2954372/difference-between-spi-and-api
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值