参考MysqlJDBC驱动源码实现⾃定义驱动⼀、分析Mysql JDBC
平常我们直接以JDBC连接数据库代码基本都如下:
Connection con = null; //创建⽤于连接数据库的Connection对象
try {
Class.forName("sql.jdbc.Driver");// 加载Mysql数据驱动
con = Connection(
"jdbc:mysql://localhost:3306/myuser", "root", "root");// 创建数据连接
} catch (Exception e) {
System.out.println("数据库连接失败" + e.getMessage());
}
return con; //返回所建⽴的数据库连接
1、我们使⽤Mysql JDBC的时候需要先注册加载驱动:
Class.forName("sql.jdbc.Driver");
利⽤jdk反射机制的真实注册过程如下:
sql.jdbc;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//执⾏这个静态代码块
static {
try {//注册mysql实现的驱动类
java.isterDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
霍元甲歌词public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
接着我们进⼊java.isterDirver(new Driver())源码:
生日短信/**
* Registers the given driver with the <code>DriverManager</code>.
* A newly-loaded driver class should call
* the method <code>registerDriver</code> to make itself
* known to the <code>DriverManager</code>.
委托书的写法*
* @param driver the new JDBC Driver that is to be registered with the
* <code>DriverManager</code>
* @exception SQLException if a database access error occurs
*/
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
if (!initialized) {
initialize();//初始化
}
DriverInfo di = new DriverInfo();//存储驱动器信息
di.driver = driver;
di.driverClass = Class();
di.driverClassName = Name();
drivers.addElement(di);//注册到驱动集合
println("registerDriver: " + di);
}
再进⾏⼀些细节的初始化⼯作驱动就注册加载完成了,有兴趣可⾃⼰看源码。接着我们如何创建连接。
2、创建数据连接
我们进去看看这个⽅法的实际执⾏过程
public static synchronized Connection getConnection(String url,
String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties();
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = CallerClassLoader();
if (user != null) {
info.put("user", user);//获取⽤户名
}
if (password != null) {
info.put("password", password);//获取密码
}
return (getConnection(url, info, callerCL));//①
}
接着我们再看①处的代码执⾏过程
// Worker method called by the public getConnection() methods.
private static synchronized Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
if(callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("Connection(\"" + url + "\")");
if (!initialized) {
initialize();
}
// Walk through the loaded drivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for (int i = 0; i < drivers.size(); i++) {//遍历驱动集合
DriverInfo di = (DriverInfo)drivers.elementAt(i);
// If the caller does not have permission to load the driver then
// skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
println(" skipping: " + di);
continue;
}
try {
println(" trying " + di);
//在注册的驱动集合中得到相应的连接①
Connection result = t(url, info);
春光灿烂猪八戒片尾曲if (result != null) {
// Success!
println("getConnection returning " + di);
return (result);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
}
所以上⾯的①处的代码实际执⾏的就是sql.jdbc.Driver的connect(url,info)⽅法
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;
}
if (!"1".Property(NUM_HOSTS_PROPERTY_KEY))) {
return connectFailover(url, info);
}
try {//初始化链接
Connection newConn = sql.Instance(
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) {
SQLException sqlEx = ateSQLException(Messages
.getString("NonRegisteringDriver.17") //$NON-NLS-1$
+ ex.toString()
+ String("NonRegisteringDriver.18"), //$NON-NLS-1$
SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);
sqlEx.initCause(ex);
throw sqlEx;
企业名称大全}
}
⼆、⾃定义驱动 Class.forName("org.tinygroup.dbrouterjdbc3.jdbc.TinyDriver"); conn =
lass TinyDriver implements Driver { private RouterManager manager; private Logger logger = Logger(TinyDriver.class); static { try {
connect(String url, Properties info) throws SQLException { if (!acceptsURL(url)) { return null; } String routerName =
url.substring("jdbc:dbrouter://".length()); Router router = Router(routerName); String user = Property("user"); String password = Property("password"); if (!user.UserName())) { logger.logMessage(LogLevel.ERROR, "username {0} and {1} not equals", user, UserName()); throw new SQLException("username not equals"); } if (!password.Password())) { logger.logMessage(LogLevel.ERROR, "password {0} and {1} not equals", password, Password()); throw new
SQLException("password not equals"); } return new TinyConnection(routerName); } 通过以上的分析我们可以通过对JDBC进⾏包装就能做到多数据源,甚⾄可以在JDBC层上进⾏分库分表。这样做的好
处是对于上层开发⼈员是透明的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论