SPI:Service Provider Interface
它是从java 6 开始引入的,是一种基于classLoader来发现并加载服务的机制
一个标准的SPI,由三个组件构成,分别是:
- service
service:是一个公开的借口和抽象类,定义了一个抽象的功能模块。 - service provider
service provider:是service接口的实现类。 - serviceLoader
serviceLoader:是SPI机制中的核心组件,负责在运行时发现并加载service Provider。对应的是JDK中serviceLoader类,调用他load方法,就可在运行时发现和加载service provider
上面的图介绍了SPI运行流程,application程序开始,使用serviceLoader加载provider(第三方家jar包中的service provider,service provider实现了service 接口,jar包中可以实现多个serivce provider,application并不关心实现类的逻辑,只关心通过service接口返回他想要的结果)。
Java SPI在JDBC中应用
JDBC,全称Java DataBase Connectivity
- JDBC是使用java语言来访问数据库的一套API
- 每个数据库厂商都会提供各自JDBC实现
我们来看看JDBC的流程
1、在Java SPI出现之前,我们是怎样来使用JDBC的:
//1.加载驱动(使用Class.forName方法)
Class.forName("com.mysql.jdbc.Driver");
//2.打开数据库连接
connection conn = DriverManager.getConnection(url,user,password);
//3.执行SQL语句(使用Statement类)
Statment st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from table_user limit 1");
//4.处理结果集(使用ResultSet类)
while(rs.next()){
System.out.printLn(rs.getInt("id"));
}
//5.关闭连接
rs.close();
st.close();
conn.close();
在加载驱动时,程序员们使用Class.forName来加载驱动,
mysql使用Class.forName(“com.mysql.jdbc.Driver”),
而oracle使用Class.forName(“orcle.jdbc.driver.OracleDriver”),
SQLServer使用Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”)
这样采用硬编码方式耦合性太高,我们可以将驱动类型写入到第三方jar包配置文件中,这样可能会好一点。只需要引入jar包就可以直接使用了,这不就是我们的SPI机制吗。
SPI出现后我们怎么使用呢?
//1.引入数据库驱动Jar包(例如mysqljar包,mysql-connector-java..jar)
//2.打开数据库连接
connection conn = DriverManager.getConnection(url,user,password);
//3.执行SQL语句(使用Statement类)
Statment st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from table_user limit 1");
//4.处理结果集(使用ResultSet类)
while(rs.next()){
System.out.printLn(rs.getInt("id"));
}
//5.关闭连接
rs.close();
st.close();
conn.close();
SPI的三大要素
- 规范的配置文件
-
文件路径:必须在JAR包中的META-INF/service目录下
-
文件名称:service接口的全限定名
-
文件内容:Service实现类(即Service Provider类)的权限定名。如果有多个实现类,每一个实现类在文件中单独占据一行
- Service Provider类必须具备无参的默认方法
Service接口的实现类,即Service Provider类,必须具备无参的默认构造方法。因为随后通过技术实例化他时,时不带参数的。 - 保证能加载到配置文件和Service Provider类:
方式一:将Service Provider的JAR包放在classpath中(最常用)
方式二:将JAR包安装到JRE的拓展目录中
方式三:自定义一个ClassLoader
举个栗子:
1.使用约定的配置文件
2.谁提供jar包,也负责提供配置文件:该内聚低耦合,代码+配置
3.使用ClassLoader的getResource和getResources方法,来读取classpath的配置文件
我们来看看SpringBoot的自动配置
SpringBoot的自动配置核心实现:
1、使用约定的配置文件:
- 文件路径是MEAT-INF/spring.factories
- 文件内容是"key=value1,value2,…"的格式。其中key是"EnableAutoConfigration"的类名,value为自动配置的类名
2、提供自动配置类的jar包中,也同时提供配置文件MEAT-INF/spring.factories
3、和SPI一样:使用ClassLoader的getResource和getResources方法来读取classpath中的配置文件
举个栗子:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)