从JDBC源码带你了解服务提供者框架

工作一年,一直想写博客记录和分享一些想法,做一名分享的Coder,尽力去写一些高质量的博文。希望能够坚持下去,对博文有建议或意见的朋友们可以联系我。

个人邮箱:zhangshaoqiangchn@gmail.com

前言:

首先让我们回忆一下在编写JDBC代码的时候,我们在获取Connection的时候怎么获取的

        Class.forName("com.mysql.jdbc.Driver");
        Connection connection= DriverManager.getConnection("jdbc:mysql:///mydatabase", "root", "root");
  1. 通过反射的方式将com.mysql.jdbc.Driver的class文件通过类加载器加载到内存中
  2. 通过DriverManager得到Connection

第一步我们通常叫注册驱动,那什么叫做注册驱动?都是通过什么实现的注册驱动呢?下面让我们带着问题去了解服务提供框架。


定义:

多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。——–《Effective Java》

组件:

  1. 服务接口(Service Interface):提供者去实现的。
  2. 提供者者注册API(provider Registration API):系统用来注册实现的。
  3. 服务访问API(Service Access API):客户端用来获取实例的。
  4. 服务提供者API(Service Provider Interface)(可选):创建其服务实例对象的。

实际场景:

sun公司在制定JDBC这套规则的时候,如果MySQL还没有出现,sun公司会再给MySQL重新制定一套规则吗?一定不会吧,可是这个问题怎么解决?

步骤:

1.所以sun公司首先自己定义了一套服务接口,就是这些这些主要步骤的定义。
2.MySQL服务商去实现这套接口。
3.现在调用者想使用MySQL提供的服务,首先进行注册,也就是调用提供者者注册API,将MySQL的实现的服务提供者接口添加到JDBC的注册列表中。
4.注册之后调用者只需要调用 服务访问API,告之我要使用哪一个SQL服务商的实现类,服务访问API就会调用服务提供者接口的实现返回对应的服务实例。

这里要说明一点因为服务的实现都是后于JDBC规则出现的,所以想实例化这些对象只能通过反射进行实例化,按照类名进行注册,所以服务提供者接口 的实现负责创建其服务实现的实例。同时使用服务提供者接口进行注册,对于MySQL而言就是Driver。

第一:让我们来看一下MySQL是怎么实现的服务注册:

com.mysql.jdbc.Driver.java

package com.mysql.jdbc;

import com.mysql.jdbc.NonRegisteringDriver;
import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can\'t register driver!");
        }
    }
}

java.sql.DriverManager.java

 // List of registered JDBC drivers
 private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<DriverInfo>();

    public static synchronized void registerDriver(java.sql.Driver driver)
        throws SQLException {
        if(driver != null) {
            registeredDrivers.addIfAbsent(new DriverInfo(driver));
        } else {
            throw new NullPointerException();
        }
        println("registerDriver: " + driver);

    }

java.sql.Driver就是服务提供者接口,NonRegisteringDriver就是其实现类,com.mysql.jdbc.Driver只是进行注册。在静态代码块中调用了DriverManager.registerDriver方法,并且将实现类添加到JDBC的注册列表(registeredDrivers)。所以在我们通过反射加载com.mysql.jdbc.Driver就可以完成注册了。这也就是文章开头问题的答案

第二:让我们来看一下客户端是怎么调用服务

1.首先通过getConnection获取

DriverManager.getConnection("jdbc:mysql:///mydatabase", "root", "root");

2.
java.sql.DriverManager.java

  public static Connection getConnection(String url)
        throws SQLException {

        java.util.Properties info = new java.util.Properties();

        // Gets the classloader of the code that called this method, may
        // be null.
        ClassLoader callerCL = DriverManager.getCallerClassLoader();

        return (getConnection(url, info, callerCL));
    }

3.
java.sql.DriverManager.java( 这是getConnection方法中的片段)

 for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerCL)) {
                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }
        }

重点是遍历registeredDrivers 这就上面注册服务的注册列表
aDriver.driver.connect(url, info);
这个就是服务提供者进行自己实现的方法,如果URL符合提供者自己的规则就返回对应Connection
(MySQL是通过字符串前缀进行匹配的,有兴趣的朋友可以自行查看源码)

总结:

所以对于JDBC来说Connection就是服务接口,DriverManager.registerDriver是提供者注册API,DriverManager.getConnection是服务访问API,Driver是服务提供者接口

其实服务提供者框架作用主要是就是隐藏子类实现,而且可以不断的进行扩展,同时将这些服务整合到一起,使调用者察觉不到子类的不同。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值