Java平台扩展机制#2:Services

来源:互联网 发布:手机淘宝下载安装 编辑:程序博客网 时间:2024/06/01 09:48

上一篇文章已经聊完了Java平台在jar包级别的扩展,现在来看看另一个在接口级别上的扩展方案。

ServiceLoader

这个方案里面,有三个东东要先搞清楚,Service,ServiceProvider,ServiceLoader。

A service is a well-known set of interfaces and (usually abstract) classes. A service provider is a specific implementation of a service.

而ServiceLoader就是用来找到提供了Service的ServiceProvider,有点依赖注入的意思。ServiceLoader如何找到ServiceProvider呢?

A service provider is identified by placing a provider-configuration file in the resource directory META-INF/services. The file's name is the fully-qualified binary name of the service's type. The file contains a list of fully-qualified binary names of concrete provider classes, one per line.

ServiceProvider可以理解为是第三方提供的jar包,ServiceLoader就是用来按照约定找出jar包中具体提供服务的Class。

这其实就是一个面向接口编程的思想。talk is cheap,下面还是举个栗子,直观一些。

举个栗子

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry:my.sql.Driver

接下来看看使用DriverManager的方式。

public Connection getConnection() throws SQLException {    Connection conn = null;    Properties connectionProps = new Properties();    connectionProps.put("user", this.userName);    connectionProps.put("password", this.password);    if (this.dbms.equals("mysql")) {        conn = DriverManager.getConnection(                   "jdbc:" + this.dbms + "://" +                   this.serverName +                   ":" + this.portNumber + "/",                   connectionProps);    } else if (this.dbms.equals("derby")) {        conn = DriverManager.getConnection(                   "jdbc:" + this.dbms + ":" +                   this.dbName +                   ";create=true",                   connectionProps);    }    System.out.println("Connected to database");    return conn;}

冲进DriverManager内部看看它是怎么使用ServiceLoader的。

    /**     * Load the initial JDBC drivers by checking the System property     * jdbc.properties and then use the {@code ServiceLoader} mechanism     */    static {        loadInitialDrivers();        println("JDBC DriverManager initialized");    }

初始化的就时候就去loadInitialDrivers

private static void loadInitialDrivers() {    ...    ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);    ...}

到MySQL官网下载JDBC驱动来瞧瞧,


java.sql.Driver文件里面的内容是

com.mysql.jdbc.Drivercom.mysql.fabric.jdbc.FabricMySQLDriver

其他配置点

我把调用了ServiceLoader.load去需找ServiceProvider的地方称为配置点,因为在这些地方我们可以去订制我们的Service。除了上面DriverManager的栗子,我们再来看看其他一些配置点。

  • Annotation Processor?这是个Service,Lombok就是用它来实现的,只是我还没找着这个Service对应的配置点是在哪,囧。

参考资料

  • http://docs.oracle.com/javase/tutorial/ext/basics/spi.html
  • http://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html

0 0
原创粉丝点击