Aaron Johnson对Class.forName()的解释_翻译

A reader asked a question via a comment a couple months ago that I didn't really have an answer for (and had always kind of wondered the same thing). In the original post (which showed how to use JDBC with ColdFusion), I used the following snippet of code:
几个月之前,一个读者通过一篇评论向我提了一个问题,我一直没有真正给出答案(我一直在考虑一件事情)。我在原来的职位(我负责展示如何在ColdFusion上使用JDBC)时,我曾使用下面的代码片断:


Class.forName("jdbc.DriverXYZ");
Connection con = DriverManager.getConnection(url,
"myLogin", "myPassword");

and the reader wanted to know what the
Class.forName(..) method did. The most common answer you'll hear is that it loads the database driver, which, while technically true, is shallow. Where does it get loaded? How does it happen? And why?

那位读者想知道Class.forName(..) 方法到底做了些什么。通常你所听到的大多数回答都是它是用来加载数据库驱动的,虽然这个答案在技术上来说是正确的,但是太浅显了。到底是在哪里加载的?是怎么工作的?还有为什么要这样用?

To answer the question I started with the JavaDoc for the Class.forName() method. According to the documentation, the method:
... attempts to locate, load, and link the class or interface.I wasn't perfectly clear on what "locate, load, and link" meant, so I did a little digging through the
Java Language Specification. According to chapter 12 of the JLS: Loading refers to the process of finding the binary form of a class or interface type with a particular name, perhaps by computing it on the fly, but more typically by retrieving a binary representation previously computed from source code by a compiler, and constructing, from that binary form, a Class object to represent the class or interface.Next, again according to the JLS, it must be transformed from it's binary representation to something the Java virtual machine can use, this process is called linking. Finally, the class is initialized, which is the process that executes the static initializer and the initializers for static fields declared in the class.

要回答这个问题,我从Java文档中关于Class.forName()方法说明开始。根据文档的说明:…试图定位,加载,连接类或者接口。我不是很清楚到底“定位,加载和连接”是什么意思,因此我小小的研究了一下《Java 语言说明书》。根据其第12章关于JLS的说明:加载是指-根据指定的类或者接口的名字,找到其实际二进制文件的处理过程,或许是很匆忙的处理,但更典型的是指检索之前被编译器编译过的二进制文件,并且构造,二进制文件就是.class文件,它可能是类或接口。接着,还是依据JLS,二进制文件将被转化为Java虚拟机可以使用的东西,这个操作称为“连接”。最后类被初始化,如执行其静态初始化程序与初始化类中声明的静态变量。


So then back to the original problem, when Class.forName() is called with an argument like this:
所以我们现在回到最开始的问题,当Class.forName()被调用时,会有参数传入就像这样:

Class.forName("org.gjt.mm.mysql.Driver");

the classloader attempts to load and link the
Driver class in the "org.gjt.mm.mysql" package and if successful, the static initializer is run. The MySQL Driver (download the source code) static initializer looks like this:
类加载器尝试去加载和连接"org.gjt.mm.mysql"包里的Driver类,如果成功了,静态初始化程序将被运行,

MySQL Driver类(在这里下载源代码)静态初始化程序是这样的:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}

So it calls a static method in the
java.sql.DriverManager class which apparently registers a copy of itself when it loads.

从上面的代码中可以看到,它调用了java.sql.DriverManager的静态方法,很显然在它被加载的时候,它注册了一个自己的实例。


So now I understand the where and the how, what about why? To understand the why you have to look at the next line in the initial code example:
因此到目前为止我明白了在哪里加载与如何加载的,但是为什么非要这么做呢?想要了解为什么,你需要看下面的初始化代码样例:


Connection con = DriverManager.getConnection(url,
"myLogin", "myPassword");

The
DriverManager class (view DriverManager source here) returns a database connection given a JDBC URL string, a username and a password. In order to create that connection, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it (ie: the registerDriver(Driver driver) method illustrated above) and calls the acceptsURL(url) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.
So there you have it. Class.forName explained.

DriverManager类在给予它一个JDBC URL字符串,一个用户名与密码后,它会返回一个数据库的连接对象,DriverManager类需要知道你要使用哪个数据库驱动程序。要做到这一点,它要遍历一个驱动数组(内部由一个Vector实现),那些驱动就是之前注册过的(例如:上文中的registerDriver(Driver driver)方法)并且逐个调用数组中驱动类的acceptsURL(url)方法,实际上是让驱动程序反馈其是否可以处理这个 JDBC URL连接字符串。直到现在你该明白Class.forName的作用了吧。^_^

 

你可能感兴趣的:(sql,mysql,jdbc,IE,ColdFusion)