P6Spy源码分析,理解跟踪SQL的工作原理

P6Spy是记录JDBC调用日志信息的一个工具,既然记录了JDBC调用,当然就可以监听到SQL,是开发人员必备的开发利器.可以让开发人员非常方便的知道当前应用程序执行了那些sql

P6Spy官方网站http://www.p6spy.com/index.html

在介绍P6Spy工作原理之前先回忆下传统jdbc的取得连接的方法
Class.forName("oracle.jdbc.driver.OracleDriver");//动态加载oracle.jdbc.driver.OracleDriver类,有关类加载这里就不做介绍了.
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);//加载驱动后就可以取得连接了

多么经典的一段代码啊,通俗的说sun定义了一套jdbc接口,由各个数据库厂商去实现,其中java.sql.Driver是一个核心接口,该接口核心方法 boolean acceptsURL(String url) ,以OracleDriver为例,oracle.jdbc.driver.OracleDriver类实现了Driver接口,当显示的调用 Class.forName("oracle.jdbc.driver.OracleDriver");时,OracleDriver会被加载,执行static{}块内的代码,做些初始化工作.当然一个应用往往有时会连接多个数据库,所以衍生了DriverManager类,这个类负责管理多个数据库驱动,也就是多个driver对象,这也是为什么Driver接口有个方法叫acceptsURL的原因,因为当DriverManager管理多个driver对象的时候,调用DriverManager.getConnection(URL, USERNAME, PASSWORD);时,DriverManager必须知道当前Url请求的是那个数据库,最直接的实现想法就是循环遍历每个驱动调用驱动的acceptsURL方法,如果返回true的话,则返回该驱动的连接,所以每个数据库驱动定义的URL格式都不同,因为必须每个驱动都能识别多自己的URL. 同时DriverManager还提供registerDriver和deregisterDriver方法,前者将驱动实例添加到DriverManager类的容器中,后者将驱动从容器中删除,就是所谓的注册驱动和反注册驱动.


上面介绍了JDBC的基本工作原理,下面介绍下P6Spy的配置,首先要改驱动,例如把应用中写com.microsoft.jdbc.sqlserver.SQLServerDriver的地方改为com.p6spy.engine.spy.P6SpyDriver,无论是连接池还是经典的jdbc.然后在spy.properties驱动中配置realDriver,这里是真正的驱动com.microsoft.jdbc.sqlserver.SQLServerDriver,然后将p6spy.jar放到classpath中即可.至于其他输出形式的配置就不介绍了,例如sqlprofiler等.

了解了P6Spy的配置,下面来看P6Spy的源码,首先声明源码已经被我改过了,只保留了最最核心的东西,所以下面的源码和真实的P6Spy源码有些不同,但核心的方法和思想都是一样的,原来的方法中大量的辅助功能和配置参数判断,代码过长不便于贴出来分析. 由于本人文采不佳所以决定通过在代码上面添加注释的方式来讲解代码.

package  com.p6spy.engine.spy;

import  java.util.ArrayList;
import  java.util.Enumeration;
import  java.util.List;
import  java.util.ResourceBundle;

public   class  P6SpyDriver  extends  P6SpyDriverCore {

    
static  { //  Class.forName("com.p6spy.engine.spy.P6SpyDriver");当加载这个类时会触发此程序块
        init();
    }

    
/**
     * 初始化过程,本方法原名initMethod,由于父类也有此名称static方法不能重载为了避免引起奇异改为init
     
*/
    
public   static   void  init() {
        List driverNames 
=   new  ArrayList(); //  存放真实驱动的驱动名容器
         try  {
            loadDriverNames(driverNames);
//  从配置文件加载真实驱动的驱动名
             if  (driverNames  ==   null   ||  driverNames.size()  ==   0 )
                
return ;
            P6SpyDriverCore.initMethod(driverNames);
//  核心方法
        }  catch  (Throwable e) {
            e.printStackTrace();
        }
    }

    
private   static   void  loadDriverNames(List driverNames) {
        
try  {
            ResourceBundle resources 
=  ResourceBundle.getBundle( " spy-drivers " );
            Enumeration keys 
=  resources.getKeys();
            
while  (keys.hasMoreElements()) {
                driverNames.add(resources.getString(keys.nextElement()
                        .toString().trim()));
            }
        } 
catch  (Throwable e) {
            e.printStackTrace();
            driverNames.add(
" oracle.jdbc.driver.OracleDriver " );
            driverNames.add(
" com.microsoft.jdbc.sqlserver.SQLServerDriver " );
            driverNames.add(
" com.mysql.jdbc.Driver " );
            driverNames.add(
" COM.ibm.db2.jdbc.net.DB2Driver " );
            driverNames.add(
" com.informix.jdbc.IfxDriver " );
            driverNames.add(
" org.hsqldb.jdbcDriver " );
        }
    }

 
}
 
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值