PGjdbc源码试读(一)
目标
通过追踪常用的jdbc方法去熟悉PGjdbc的执行流程
常见jdbc使用流程
Class.forName("org.postgresql.Driver");
Connection connectionPG = DriverManager.getConnection("jdbc:postgresql://localhost:5432/xxx","xxxxxx","xxxxxx");
Statement statement =connectionPG.createStatement();
statement.executeUpdate(sql);
追踪
查看引用
引入的包如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
java.sql包主要是定义了一些接口规范,具体实现由各个数据库的jdbc实现,因而我们需要去PGjdbc里找对应接口的实现类,继而追踪各个方法的实现过程
追踪Class.forName
首先在PGjdbc源码中找到org.postgresql.Driver,其位于pgjdbc-master\pgjdbc\src\main\java\org\postgresql\Driver.java,该类实现了java.sql.Driver接口,通过观察源码可知,该类存在静态代码块,当执行Class.forName对其进行动态加载时,其将执行该代码块,如下:
该register()方法如下:
由此可知,当执行动态加载时,将执行静态代码块里的语句,实现该驱动的自动加载和注册。对DriverManager.registerDriver()进行追踪,其最终效果为将新建的Driver置于如下
数组中。
追踪DriverManager.getConnection
函数追踪如下:
由以上代码可知,该方法只是检查一下参数,继续追踪:
该方法核心部分如下:
其遍历registeredDrivers(如上截图),并尝试使用每个驱动程序连接到数据库,成功的一个就是目标连接。我们发现该连接是通过Driver类的connect方法实现的,继续追踪至该方法:
该方法较长,简单来说,该方法的作用为加载默认配置到配置类对象中,并解析url,将其中的一些配置加载到PGProperty里存储的一些枚举常量中。值得注意的是,该方法中有如下代码块:
该部分调用了一个从本地加载配置文件的方法,在追踪过程中,并未发现方法体内指定的文件(该方法体未截图),不知是否会在某过程中生成。继续往下看,本方法有关连接的核心部分如下:
因为我们未设置超时参数,故选择追踪 makeConnection
追踪到PGConnection的构造函数(复杂,单独记录):
该函数结合了info对象和本地枚举类PGProperty里存储的一些枚举常量,对PGConnection里的各个属性进行了配置,个人认为,该部分info对象和PGProperty的一些枚举常量的组合写法,是一种很妙的写法。
debug追踪
在之前的各个位置打上断点,选择org.postgresql.jdbc.ConnectionValidTest文件里的:
进行debug。
停顿
第一处
第二处
第三处
第四处
第五处
总结
- 当我们动态加载Driver类时,其将执行静态代码块,新建一个Driver对象,并存储到DriverManager的registeredDrivers中,当然registeredDrivers数组并不是一个Driver类型的List,在此处不讨论这个结构。
- 当我们使用DriverManager新建一个Connection时,其会将本地文件(未找到,待深究)里的配置信息加载至配置对象中,并将我们传入的url中的一些配置信息提取出来,并去修改PGProperty里对应的枚举常量对象,当最后进入到PGConnection的构造方法中时,PGConnection中的对象属性就将从两者中获得,原理为,配置对象中有则取配置对象中的信息,无,则取PGProperty里对应的枚举常量信息。从作用上来推测,未找到的该文件应该是默认配置的定义信息或修改信息。
才疏学浅,随学随改