mysql驱动注册机制演变

先上一段很原始的纯JDBC操作mysql代码

Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8", "root", "123456");
try {
 String sql = "select CURRENT_TIMESTAMP";
 Statement stmt = connection.createStatement();
 try {
  ResultSet rs = stmt.executeQuery(sql);
  try {
   while (rs.next()) {
    System.out.println(rs.getTimestamp("CURRENT_TIMESTAMP"));
   }
  } finally {
   rs.close();
  }
 } finally {
  stmt.close();
 }
} finally {
 connection.close();
}

很简单的纯jdbc操作数据示例,相信大家在接触java初涉数据库部分的时候,都学习过这段代码,今天我想说说第一行代码

第一行之所以能够注册驱动,是因为在com.mysql.jdbc.Driver实现中,存在一个静态代码块,调用了 java.sql.DriverManager.registerDriver(new Driver()); 这就注册驱动了

第一行也可以改写成:DriverManager.registerDriver(new com.mysql.jdbc.Driver());
这是最早的两种注册驱动机制了,不过这种机制存在一个问题,就是不遵守直线型代码约定,所谓直线型代码就是代码在所处上下文环境中依赖关系非常的明显,如下:

data = ReadData();
results = CalculateResultsFromData(data);
PrintResults(results);

这段代码有着非常明确的顺序,第三条依赖第二条,第二条依赖第一条,而下面这种写法,依赖关系就不明显了。

revenue.ComputeMonthly();
revenue.ComputeQuarterly();
revenue.ComputeAnnual();

前面注册驱动的写法,与这个类似,依赖关系不明显,很可能导致在实现的时候或者维护的时候发生漏写(没有注册驱动而出错的例子还是经常发生)、顺序错乱而编译期发现不了的问题
上面两个例子摘自《代码大全2》,根据《代码大全2》中的指导思想,我们首先要尽力写没有顺序依赖关系的代码,其次尽力写依赖关系明显的代码。

自JDK1.6开始,提供了ServiceLoader,可以主动加载服务,并且在jdk自带的DriverManager中也完善了驱动扫描实现,关键实现代码如下:

AccessController.doPrivileged(new PrivilegedAction<Void>() {
    public Void run() {
        ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
        Iterator<Driver> driversIterator = loadedDrivers.iterator();
        /* Load these drivers, so that they can be instantiated.
         * It may be the case that the driver class may not be there
         * i.e. there may be a packaged driver with the service class
         * as implementation of java.sql.Driver but the actual class
         * may be missing. In that case a java.util.ServiceConfigurationError
         * will be thrown at runtime by the VM trying to locate
         * and load the service.
         *
         * Adding a try catch block to catch those runtime errors
         * if driver not available in classpath but it's
         * packaged as service and that service is there in classpath.
         */
        try{
            while(driversIterator.hasNext()) {
                driversIterator.next();
            }
        } catch(Throwable t) {
        // Do nothing
        }
        return null;
    }
});

关于ServiceLoader的使用方式,大家自行查看API即可,已经够详细了。
于是在mysql驱动5.1.6版本开始(mysql-connector-java-5.1.6.jar),利用了这个机制,大家可自行下载5.1.6版本之后的jar查看,存在文件:META-INF/services/java.sql.Driver
文件内容:com.mysql.jdbc.Driver

自此之后,大家写纯jdbc的时候,就不需要自己注册驱动了 Class.forName(“com.mysql.jdbc.Driver”); 这样就省掉了一行不那么规范的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值