Druid的數據庫連接獲取過程以及是否可熱切換域名

爲什麼寫?我就想看看,到底和普通建立當有啥區別,另外是否可以熱切換域名

普通的Mysql創建連接的過程:

public class Conn {
    Connection con;
    public Connection getConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");  
            System.out.println("數據庫驅動加載成功");
        } catch(ClassNotFoundException e){
            e.printStackTrace();
        }
        try {
            con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mysql?characterEncoding=UTF-8","root","");
            System.out.println("數據庫連接成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }
}

Druid創建數據庫連接過程:
DruidDataSourceAutoConfigure配置實例化數據源DataSource,同時@Bean(initMethod = "init")會將init作爲初始化方法設置到AbstractBeanDefinition中initMethodName裏邊,所以在實例化DataSource之後,將執行DataSource的init方法進行初始化,初始化過程中會將調用DruidDriver.getInstance()方法觸發Druid數據庫驅動注入DriverManager.registerDriver(driver),之後會加載mysql數據庫驅動設置到druid datasource裏邊,但是這裏使用的不是Class.forName("com.mysql.jdbc.Driver"),而是使用線程上下文加載器Thread.currentThread().getContextClassLoader()進行loadClass,Class.forName會觸發靜態初始化塊,上下文類加載器默認不會觸發靜態初始化塊,而之後的newInstance實例化mysql驅動的過程會調用靜態初始化塊進行註冊。
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

druid在獲取數據庫連接的時候直接調用mysql驅動實現類NonRegisteringDriver獲取。而不是DriverManager進行獲取,當然DriverManager的獲取方式的底層實現仍然是通過NonRegisteringDriver進行獲取的。但是這裏邊總感覺失去了DriverManager的靈魂判斷

  private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
        boolean result = false;
        if(driver != null) {
            Class<?> aClass = null;
            try {
                aClass =  Class.forName(driver.getClass().getName(), true, classLoader);
            } catch (Exception ex) {
                result = false;
            }

                // 注意,只有同一個類加載器中的Class使用==比較時纔會相等,此處就是校驗用戶註冊Driver時該Driver所屬的類加載器與調用時的是否同一個,DriverManager是被Bootstrap類加載器加載的,也就是說isDriverAllowed的執行加載器是Bootstrap,而傳參classLoader是上下文加載器,很有趣的是,上下文加載器可以破壞雙親委託機制。
 result = ( aClass == driver.getClass() ) ? true : false;
        }

        return result;
    }

那還有個疑問,如果使用域名作爲數據庫連接,是否可以不重啓服務而切換域名呢,可以。原因Druid存在一個wait重試線程CreateConnectionThread,當斷開連接後,獲取線程會執行activeCount--當activeCount <= minIdle最小連接數時候,會執行empty.signal(),將CreateConnectionThread被喚起,重新進行連接建立,而MysqlIO在執行socketFactory.connect(this.host, this.port, props);的時候會使用InetAddress.getAllByName(this.host)進行DNS域名解析

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章