Class.forName()做了什么?
2016-03-13 20:01
411 查看
JDBC连接一般需要以下步骤:
1 加载驱动
2 获取连接对象
3 创建命令对象
4 执行sql语句
但是有疑问的是第一步,没有返回对像,追踪到源码:
后面几步获取的对象一般都是方便下一步的调用,所以Class.forName()到底如何执行的,以及做了哪些工作,知悉了这些,才能对JDBC连接的理解更加透彻。
在这里首先贴出Driver类源码:
从中可以获取以下信息:
每个驱动类都必须实现Driver接口
当驱动被加载的时候,它首先实例化对象,并将其注册到DriverManager。
com.mysql.jdbc.Driver中的部分代码:
在初始化Driver类的时候,其中的静态代码也会执行,于是乎自动执行下面的语句:
就这样,使用forName()初始化Driver后,MySql驱动就自动向DriverManagemer类注册了,使得我们能通过DriverManager获得对MysqL的连接。
贴出registerDriver()源码解释:
部分实现代码:
new DriverInfo(driver),接下来在看一下DriverInfo(driver)类:
DriverInfo非常简单,用于保存Driver的信息,只有3个成员变量,Driver,DriverClass和 DriverClassName,意义非常明显。
在一个类加载入内存的时候,类中的静态初始化过程会执行,这样就完成了驱动程序的注册过程。然后重点看一下建立数据库连接的代码,在getConnection函数中,
实现函数:
到这里基本完成连接了。接下来,考虑一下,源码中说尝试一个合适的驱动从注册的JDBC驱动中,轮询方式,当注册的驱动多了,连接速度会越慢。JDBC连接数据库的速度很慢, 是不是和这种实现方式有关联呢?看一下Driver类:
看一下NonRegisteringDriver的实现:
先parseURL,然后使用Connection去建立连接。parseURL只是简单的字符串分析,主要是分析传入的连接字符串是否满足 “jdbc:mysql://host:port/database“的格式,如果不满足,直接返回null,然后由DriverManager去试验下 一个Driver。如果满足,则建立一个Connection对象建立实际的数据库连接,由此可见刚刚的问题答案是:DriverManager的轮询查询注册的Driver对象的工作方式所带来的性能代价并不是很大,主工作量只是parseURL函数。
源码追溯到这里结束了,剩下的就不去管了。
1 加载驱动
Class.forName("com.mysql.jdbc.Driver");
2 获取连接对象
Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306/homeworksubmit?user=root&password=root&useUnicode=true&characterEncoding=UTF-8");
3 创建命令对象
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
4 执行sql语句
Result rs=stmt.executeQuery(sql);
但是有疑问的是第一步,没有返回对像,追踪到源码:
Returns the {@code Class} object associated with the class or interface with the given string name. equivalent to: {@code Class.forName(className, true, currentLoader)}
后面几步获取的对象一般都是方便下一步的调用,所以Class.forName()到底如何执行的,以及做了哪些工作,知悉了这些,才能对JDBC连接的理解更加透彻。
在这里首先贴出Driver类源码:
* The Java SQL framework allows for multiple database drivers. Each driver * should supply a class that implements the Driver interface * * <p> * The DriverManager will try to load as many drivers as it can find and then * for any given connection request, it will ask each driver in turn to try to * connect to the target URL. * * <p> * It is strongly recommended that each Driver class should be small and * standalone so that the Driver class can be loaded and queried without * bringing in vast quantities of supporting code. * * <p> * When a Driver class is loaded, it should create an instance of itself and * register it with the DriverManager. This means that a user can load and * register a driver by doing Class.forName("foo.bah.Driver")
从中可以获取以下信息:
每个驱动类都必须实现Driver接口
当驱动被加载的时候,它首先实例化对象,并将其注册到DriverManager。
com.mysql.jdbc.Driver中的部分代码:
在初始化Driver类的时候,其中的静态代码也会执行,于是乎自动执行下面的语句:
java.sql.DriverManager.registerDriver(new Driver());
public class Driver extends NonRegisteringDriver implements java.sql.Driver { // ~ Static fields/initializers // --------------------------------------------- // // Register ourselves with the DriverManager // static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } …… }
就这样,使用forName()初始化Driver后,MySql驱动就自动向DriverManagemer类注册了,使得我们能通过DriverManager获得对MysqL的连接。
贴出registerDriver()源码解释:
* Registers the given driver with the <code>DriverManager</code>.
部分实现代码:
public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException { /* Register the driver if it has not already been added to our list */ if(driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver)); } else { // This is for compatibility with the original DriverManager throw new NullPointerException(); } println("registerDriver: " + driver); }
new DriverInfo(driver),接下来在看一下DriverInfo(driver)类:
DriverInfo非常简单,用于保存Driver的信息,只有3个成员变量,Driver,DriverClass和 DriverClassName,意义非常明显。
在一个类加载入内存的时候,类中的静态初始化过程会执行,这样就完成了驱动程序的注册过程。然后重点看一下建立数据库连接的代码,在getConnection函数中,
/** * Attempts to establish a connection to the given database URL. * The <code>DriverManager</code> attempts to select an appropriate driver from * the set of registered JDBC drivers. * * @param url a database url of the form * <code> jdbc:<em>subprotocol</em>:<em>subname</em></code> * @return a connection to the URL * @exception SQLException if a database access error occurs */
实现函数:
@CallerSensitive public static Connection getConnection(String url) throws SQLException { java.util.Properties info = new java.util.Properties(); return (getConnection(url, info, Reflection.getCallerClass())); }
到这里基本完成连接了。接下来,考虑一下,源码中说尝试一个合适的驱动从注册的JDBC驱动中,轮询方式,当注册的驱动多了,连接速度会越慢。JDBC连接数据库的速度很慢, 是不是和这种实现方式有关联呢?看一下Driver类:
public class Driver extends NonRegisteringDriver implements java.sql.Driver
看一下NonRegisteringDriver的实现:
public java.sql.Connection connect(String url, Properties info) throws SQLException { if (url != null) { if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) { return connectLoadBalanced(url, info); } else if (StringUtils.startsWithIgnoreCase(url, REPLICATION_URL_PREFIX)) { return connectReplicationConnection(url, info); } } Properties props = null; if ((props = parseURL(url, info)) == null) { return null; } try { Connection newConn = new com.mysql.jdbc.Connection(host(props), port(props), props, database(props), url); return newConn; } catch (SQLException sqlEx) { // Don't wrap SQLExceptions, throw // them un-changed. throw sqlEx; } catch (Exception ex) { throw SQLError.createSQLException(Messages .getString("NonRegisteringDriver.17") //$NON-NLS-1$ + ex.toString() + Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$ SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); } }
先parseURL,然后使用Connection去建立连接。parseURL只是简单的字符串分析,主要是分析传入的连接字符串是否满足 “jdbc:mysql://host:port/database“的格式,如果不满足,直接返回null,然后由DriverManager去试验下 一个Driver。如果满足,则建立一个Connection对象建立实际的数据库连接,由此可见刚刚的问题答案是:DriverManager的轮询查询注册的Driver对象的工作方式所带来的性能代价并不是很大,主工作量只是parseURL函数。
源码追溯到这里结束了,剩下的就不去管了。
相关文章推荐
- 机房收费系统VB.NET版——七层登录
- 数据结构笔记-----递归与栈
- C# winform多线程的小例子
- ADO.NET常用几点
- iptables 路由转发, 将一台服务器的IP转发到另一个另一台服务器上面(远程序防护)
- 对比:通过实现Runnable接口和继承thread类来生成多线程
- 用C读取INI配置文件
- 3周《机电传动控制》学习笔记
- Photoshop的评价
- 深入Java虚拟机读书笔记之执行子系统
- Constructing module maps for integrated analysis of heterogeneous biological networks
- 安装SQL08时,出现[错误消息] 为 SQL Server 代理服务提供的凭据无效。若要继续操作,请为 SQL Serve
- CSS中position的4种定位详解
- 放养的小爬虫--拉钩网半智能整站小爬虫
- 家庭无线上网问题之信道拥挤
- 理解之软件需求说明书
- Yield的使用方法
- DataTable转泛型
- 泛型理解
- java异常处理