P6Spy源码分析-Connection获取,statement超时日志打印

P6Spy使用:[url]http://donald-draper.iteye.com/blog/2319646[/url]
P6Spy源码分析-属性文件加载:[url]http://donald-draper.iteye.com/admin/blogs/2319851[/url]
P6Spy源码分析-Connection获取,日志打印:[url]http://donald-draper.iteye.com/admin/blogs/2319873[/url]
使用P6Spy的时候用到这一句我们来看这一句的内涵:
P6DataSource p6DSource = new P6DataSource(cpDSource)
// p6DSource = new P6DataSource(cpDSource)
public class P6DataSource extends P6Base
implements DataSource, Referenceable, Serializable
{
//source是通过构造传入的数据源c3p0或Druid
public P6DataSource(DataSource source)
{
rds = source;
}
//初始化驱动及日志模块
public static void initMethod()
{
P6SpyDriverCore.initMethod((com.p6spy.engine.spy.P6SpyDriver.class).getName());
}
//获取Connection
public Connection getConnection()
throws SQLException
{
if(rds == null)
bindDataSource();
return P6SpyDriverCore.wrapConnection(rds.getConnection());
}
protected DataSource rds;
protected String rdsName;
//通过static语句块调用初始化方法
static
{
initMethod();
}
}

超时日志线路解析:
P6DataSource,的getConnection方法通过 P6SpyDriverCore.wrapConnection(rds.getConnection())获取连接;
再来看看P6SpyDriverCore的wrapConnection的方法都做了什么事情
public abstract class P6SpyDriverCore
implements Driver
{
public static synchronized void initMethod(String spydriver)
{
if(initialized)
return;
String path = P6SpyProperties.getPropertiesPath();
if(path == null)
{
foundSpyProperties = false;
return;
}
foundSpyProperties = true;
//初始化spy.properties属性文件
P6SpyProperties properties = new P6SpyProperties();
P6SpyOptions coreOptions = new P6SpyOptions();
OptionReloader.add(coreOptions, properties);
String className = "no class";
String classType = "driver";
try
{
//realdriver
ArrayList driverNames = null;
//日志模块
ArrayList modules = null;
//获取驱动名
driverNames = P6SpyOptions.allDriverNames();
//获取所有日志模块
modules = P6SpyOptions.allModules();
boolean hasModules = modules.size() > 0;
Iterator i = null;
classType = "driver";
Driver realDriver;
for(i = driverNames.iterator(); i.hasNext(); P6LogQuery.logDebug("Registered driver: " + className + ", realdriver: " + realDriver))
{
P6SpyDriver spy = null;
if(hasModules)
{
spy = new P6SpyDriver();
DriverManager.registerDriver(spy);
}
className = (String)i.next();
deregister(className);
realDriver = (Driver)P6Util.forName(className).newInstance();
if(P6SpyOptions.getDeregisterDrivers())
//注册驱动realdriver=com.mysql.jdbc.Driver
DriverManager.registerDriver(realDriver);
if(hasModules)
{
spy.setPassthru(realDriver);
realDrivers.add(realDriver);
}
}

if(hasModules)
{
factories = new ArrayList();
classType = "factory";
com.p6spy.engine.common.P6Options options;
for(i = modules.iterator(); i.hasNext(); P6LogQuery.logDebug("Registered factory: " + className + " with options: " + options))
{
className = (String)i.next();
//module.log=com.p6spy.engine.logging.P6LogFactory
//module.outage=com.p6spy.engine.outage.P6OutageFactory
P6Factory factory = (P6Factory)P6Util.forName(className).newInstance();
factories.add(factory);
options = factory.getOptions();
if(options != null)
OptionReloader.add(options, properties);
}

}
initialized = true;
for(Enumeration e = DriverManager.getDrivers(); e.hasMoreElements(); P6LogQuery.logDebug("Driver manager reporting driver registered: " + e.nextElement()));
}
catch(Exception e)
{
String err = "Error registering " + classType + " [" + className + "]\nCaused By: " + e.toString();
P6LogQuery.logError(err);
throw new P6DriverNotFoundError(err);
}
}
//P6DataSource的getConnection方法条用P6SpyDriverCore的wrapConnection(Connection realConnection)方法
public static Connection wrapConnection(Connection realConnection)
throws SQLException
{
Connection con = realConnection;
if(factories != null)
{
for(Iterator it = factories.iterator(); it.hasNext();)
{
P6Factory factory = (P6Factory)it.next();
//这里是重点,这里是通过P6Factory来获取连接,P6SpyDriverCore
//在初始化initMethod已经P6LogFactory,P6OutageFactory
//module.log=com.p6spy.engine.logging.P6LogFactory
//module.outage=com.p6spy.engine.outage.P6OutageFactory
con = factory.getConnection(con);
}

}
return con;
}
protected Driver passthru;
protected static boolean initialized = false;
protected static ArrayList factories;
protected static ArrayList realDrivers = new ArrayList();
protected static boolean foundSpyProperties;
}

这一句很重要:con = factory.getConnection(con),这个factory实际上是P6LogFactory或P6OutageFactory
再来看看P6OutageFactory的getConnection()的方法
public class P6OutageFactory extends P6CoreFactory
{ //返回P6OutageConnection
public Connection getConnection(Connection conn)
throws SQLException
{
return new P6OutageConnection(this, conn);
}
//返回P6OutagePreparedStatement
public PreparedStatement getPreparedStatement(PreparedStatement real, P6Connection conn, String p0)
throws SQLException
{
return new P6OutagePreparedStatement(this, real, conn, p0);
}
}

再看P6OutageConnection
public class P6OutageConnection extends P6Connection
implements Connection
{
//提交
public void commit()
throws SQLException
{
long startTime = System.currentTimeMillis();
//outagedetection=true
if(P6OutageOptions.getOutageDetection())
//P6OutageDetector,注册statement行为commit事件
P6OutageDetector.getInstance().registerInvocation(this, startTime, "commit", "", "");
try
{
passthru.commit();
}
finally
{
if(P6OutageOptions.getOutageDetection())
P6OutageDetector.getInstance().unregisterInvocation(this);
}
}
}

再看P6Connection
public class P6Connection extends P6Base
implements Connection
{
获取预编译Statement,看到这是不是很熟悉的JDBC的Connection.prepareStatement(String sql)
public PreparedStatement prepareStatement(String p0)
throws SQLException
{
这里条用的实际就是P6OutageFactory的getPreparedStatement的方法,返回P6OutagePreparedStatement
return getP6Factory().getPreparedStatement(passthru.prepareStatement(p0), this, p0);
}
}

再看P6OutagePreparedStatement
public class P6OutagePreparedStatement extends P6PreparedStatement
implements PreparedStatement
{

public boolean execute()
throws SQLException
{
long startTime = System.currentTimeMillis();
//outagedetection=true
if(P6OutageOptions.getOutageDetection())
//将statement注册到P6OutageDetector(statement超时探测器)
P6OutageDetector.getInstance().registerInvocation(this, startTime, "statement", preparedQuery, getQueryFromPreparedStatement());
boolean flag;
try
{
flag = prepStmtPassthru.execute();
}
finally
{
//outagedetection=true
if(P6OutageOptions.getOutageDetection())
//当statement执行完毕,将statement从P6OutageDetector(statement超时探测器)移除
P6OutageDetector.getInstance().unregisterInvocation(this);
}
return flag;
}
}

再看P6OutageOptions
//超时属性配置
//outagedetection=true
//outagedetectioninterval=5
public class P6OutageOptions extends P6Options
{
public static boolean getOutageDetection()
{
return outageDetection;
}

public static void setOutageDetection(String _outagedetection)
{
outageDetection = P6Util.isTrue(_outagedetection, false);
}

public static long getOutageDetectionInterval()
{
return outageDetectionInterval;
}

public static long getOutageDetectionIntervalMS()
{
return outageMs;
}

public static void setOutageDetectionInterval(String _outagedetectioninterval)
{
outageDetectionInterval = P6Util.parseLong(_outagedetectioninterval, -1L);
outageMs = outageDetectionInterval * 1000L;
}

protected static boolean outageDetection;
protected static long outageDetectionInterval;
protected static long outageMs;
}

再看P6OutageDetector(statement超时探测器)
//实际上是一个线程
public class P6OutageDetector
implements Runnable
{

protected P6OutageDetector()
{
pendingMessages = null;
haltThread = false;
pendingMessages = new Hashtable();
P6LogQuery.logDebug("P6Spy - P6OutageDetector has been invoked.");
P6LogQuery.logDebug("P6Spy - P6OutageOptions.getOutageDetectionIntervalMS() = " + P6OutageOptions.getOutageDetectionIntervalMS());
}
//单例模式获取探测器实例
public static synchronized P6OutageDetector getInstance()
{
if(instance == null)
{
instance = new P6OutageDetector();
ThreadGroup group = new ThreadGroup("P6SpyThreadGroup");
//放在后再运行
group.setDaemon(true);
Thread outageThread = new Thread(group, instance, "P6SpyOutageThread");
outageThread.start();
}
return instance;
}

public void run()
{
while(!haltThread)
{
detectOutage();
try
{
//睡眠outagedetectioninterval=5秒
Thread.sleep(P6OutageOptions.getOutageDetectionIntervalMS());
}
catch(Exception e) { }
}
}

public void shutdown()
{
haltThread = true;
}
//将statement注册到探测器
public void registerInvocation(Object jdbcObject, long startTime, String category, String ps, String sql)
{
//pendingMessages其实是一个HashMap,private Hashtable pendingMessages;
pendingMessages.put(jdbcObject, new InvocationInfo(startTime, category, ps, sql));
}
//将statement从探测器移除
public void unregisterInvocation(Object jdbcObject)
{
pendingMessages.remove(jdbcObject);
}
//探测是否有超时的statement
private void detectOutage()
{
int listSize = pendingMessages.size();
if(listSize == 0)
return;
P6LogQuery.logDebug("P6Spy - detectOutage.pendingMessage.size = " + listSize);
long currentTime = System.currentTimeMillis();
long threshold = P6OutageOptions.getOutageDetectionIntervalMS();
Set keys = pendingMessages.keySet();
for(Iterator keyIter = keys.iterator(); keyIter.hasNext();)
{

InvocationInfo ii = (InvocationInfo)pendingMessages.get(keyIter.next());
//判断statement是否超时
if(ii != null && currentTime - ii.startTime > threshold)
{
//打印日志
P6LogQuery.logDebug("P6Spy - statement exceeded threshold - check log.");
logOutage(ii);
}
}

}
//打印日志
private void logOutage(InvocationInfo ii)
{
P6LogQuery.logElapsed(-1, ii.startTime, "OUTAGE", ii.preparedStmt, ii.sql);
}

private Hashtable pendingMessages;
private boolean haltThread;
private static P6OutageDetector instance = null;
private static final boolean debug = true;

}

P6LogQuery类,这里就不分析了,在前面已经说过了
[size=medium]总结:[/size]
[color=green]通过以上的分析,相信大家对P6Spy超时探测,connection获取,日志打印有了
初步的了解,主要 点,static语句块,初始化类,利用工场模式获取connection,
单例模式获取探测器,日志的打印主要通过封装实现jdbc的statement来嵌入。[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值