数据库连接池DBCP框架的研究以及源代码分析二:寻找真正的DataSource

从DataSourceFactory中,我们看到DataSourceFactory创建了一个DataBaseSource,如下代码

 
    public static DataSource createDataSource(Properties properties) throws Exception {
        BasicDataSource dataSource = new BasicDataSource();
      //省略设置属性若干

     retrun  dataSource ;

}

那么BasicDatasource是什么东东?请看代码

public class BasicDataSource implements DataSource {//从这里看,好像这个类就是传说中的DataSource,但是看看下面的红色属性部分
    
    static {
        DriverManager.getDrivers();//注册驱动
    }

//这里省略SET\GET方法一堆,以免耽误代价时间,直接看属性
     protected volatile DataSource dataSource = null;//这里又定义了一个Datasource,看来BasicDataSource只是一个烟雾弹,在里面的属性,才是真正的DataSource,我们知道,DataSource接口主要是用于创建连接,那么我们看一下getConnection()就可以确认我们的猜测是否正确?,继续往下看红色部分

    protected volatile boolean defaultAutoCommit = true;
    protected transient Boolean defaultReadOnly = null;
    protected volatile int defaultTransactionIsolation =
        PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION;
    protected volatile String defaultCatalog = null;
    protected String driverClassName = null;
    protected ClassLoader driverClassLoader = null;
    protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
    protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
    protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
    protected int initialSize = 0;
    protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
    protected boolean poolPreparedStatements = false;
    protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
    protected boolean testOnBorrow = true;
    protected boolean testOnReturn = false;
    protected long timeBetweenEvictionRunsMillis =
        GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
    protected int numTestsPerEvictionRun =
        GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
    protected long minEvictableIdleTimeMillis =
        GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
    protected boolean testWhileIdle = false;
    protected volatile String password = null;
    protected String url = null;
    protected String username = null;
    protected volatile String validationQuery = null;//验证连接有效性的SQL
    protected volatile int validationQueryTimeout = -1;
    protected volatile List connectionInitSqls;
    private boolean accessToUnderlyingConnectionAllowed = false; //是否可以操作底层连接
    private volatile boolean restartNeeded = false;
     protected volatile GenericObjectPool connectionPool = null; //连接池
    protected Properties connectionProperties = new Properties();

    protected PrintWriter logWriter = new PrintWriter(System.out);
    private AbandonedConfig abandonedConfig;
    protected boolean closed;
 
    public Connection getConnection() throws SQLException {
        return createDataSource().getConnection();
//看来,这个类很狡猾,跟我们玩了一个花样,createDataSource里面创建的才是真正创造连接的DataSource接口
    }

//创建真正DataSource的类
    protected synchronized DataSource createDataSource()//核心方法
        throws SQLException {
        if (closed) {
            throw new SQLException("Data source is closed");
        }


        // 如果已经创建过一次了,就返回已经创建的,这个合情合理
        if (dataSource != null) {
            return (dataSource);
        }


        // 创建一个工厂,用于生成真正物理的Connection
        ConnectionFactory driverConnectionFactory = createConnectionFactory();


        // 创建我们的连接池

        createConnectionPool();


 
        GenericKeyedObjectPoolFactory statementPoolFactory = null;
        if (isPoolPreparedStatements()) {//如果需要缓存PrepareStatement,生成带KEY的对象池
            statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
                        -1, // unlimited maxActive (per key)
                        GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
                        0, // maxWait
                        1, // maxIdle (per key)
                        maxOpenPreparedStatements);
        }


        // 创建对象状态维护工厂类
        createPoolableConnectionFactory(driverConnectionFactory, statementPoolFactory, abandonedConfig);


        // 创建真正的DataSource来管理连接
        createDataSourceInstance();
        
        try {//初始化对象
            for (int i = 0 ; i < initialSize ; i++) {
                connectionPool.addObject();
            }
        } catch (Exception e) {
            throw new SQLNestedException("Error preloading the connection pool", e);
        }
        
        return dataSource;
    } 


    /**
     * 创建Connection工厂
     */
    protected ConnectionFactory createConnectionFactory() throws SQLException {
        // 注册驱动
        Class driverFromCCL = null;
        if (driverClassName != null) {
            try {
                try {
                    if (driverClassLoader == null) {
                        Class.forName(driverClassName);
                    } else {
                        Class.forName(driverClassName, true, driverClassLoader);
                    }
                } catch (ClassNotFoundException cnfe) {
                    driverFromCCL = Thread.currentThread(
                            ).getContextClassLoader().loadClass(
                                    driverClassName);
                }
            } catch (Throwable t) {
                String message = "Cannot load JDBC driver class '" +
                    driverClassName + "'";
                logWriter.println(message);
                t.printStackTrace(logWriter);
                throw new SQLNestedException(message, t);
            }
        }


        // 创建Driver实例
        Driver driver = null;
        try {
            if (driverFromCCL == null) {
                driver = DriverManager.getDriver(url);
            } else {
                // Usage of DriverManager is not possible, as it does not
                // respect the ContextClassLoader
                driver = (Driver) driverFromCCL.newInstance();
                if (!driver.acceptsURL(url)) {
                    throw new SQLException("No suitable driver", "08001"); 
                }
            }
        } catch (Throwable t) {
            String message = "Cannot create JDBC driver of class '" +
                (driverClassName != null ? driverClassName : "") +
                "' for connect URL '" + url + "'";
            logWriter.println(message);
            t.printStackTrace(logWriter);
            throw new SQLNestedException(message, t);
        }


        // 根据验证的SQL语句判断是否需要验证连接有效性
        if (validationQuery == null) {
            setTestOnBorrow(false);
            setTestOnReturn(false);
            setTestWhileIdle(false);
        }


        // Set up the driver connection factory we will use
        String user = username;
        if (user != null) {
            connectionProperties.put("user", user);
        } else {
            log("DBCP DataSource configured without a 'username'");
        }


        String pwd = password;
        if (pwd != null) {
            connectionProperties.put("password", pwd);
        } else {
            log("DBCP DataSource configured without a 'password'");
        }


        ConnectionFactory driverConnectionFactory = new DriverConnectionFactory(driver, url, connectionProperties);
        return driverConnectionFactory;
    }

 /**
     *创建连接池
     */
    protected void createConnectionPool() {
    
        GenericObjectPool gop;
        if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned())) {//如果有配置以及设置收回没有使用的连接
            gop = new AbandonedObjectPool(null,abandonedConfig);//生成我们带回收连接的连接池
        }
        else {
            gop = new GenericObjectPool();//生成普通连接池
        }
        gop.setMaxActive(maxActive);
        gop.setMaxIdle(maxIdle);
        gop.setMinIdle(minIdle);
        gop.setMaxWait(maxWait);
        gop.setTestOnBorrow(testOnBorrow);
        gop.setTestOnReturn(testOnReturn);
        gop.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        gop.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        gop.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        gop.setTestWhileIdle(testWhileIdle);
        connectionPool = gop;
    }

/**
     创建可池化连接工厂(对象状态维护工厂)
     */
    protected void createPoolableConnectionFactory(ConnectionFactory driverConnectionFactory,
            KeyedObjectPoolFactory statementPoolFactory, AbandonedConfig configuration) throws SQLException {
        PoolableConnectionFactory connectionFactory = null;
        try {

//由此我们可以看到,对象状态维护工厂为PoolableConnectionFactory,提供了makeObject,Destory等方法对对象进行维护。
            connectionFactory =
                new PoolableConnectionFactory(driverConnectionFactory,/
                                              connectionPool,
                                              statementPoolFactory,
                                              validationQuery,
                                              validationQueryTimeout,
                                              connectionInitSqls,
                                              defaultReadOnly,
                                              defaultAutoCommit,
                                              defaultTransactionIsolation,
                                              defaultCatalog,
                                              configuration);
            validateConnectionFactory(connectionFactory);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
        }
    }
 
    protected void createDataSourceInstance() throws SQLException {
        PoolingDataSource pds = new PoolingDataSource(connectionPool);//真正的Datasource对象,看来我们找到了,值得庆祝一下,慢慢抽丝剥茧读代码
        pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
        pds.setLogWriter(logWriter);
        dataSource = pds;
    }

--------------------------------------------------------核心代码到此完,下面的方法,即使不用脑子,用脚趾也能猜出是干嘛的--------------------------


    public Connection getConnection(String user, String pass) throws SQLException {
 
        throw new UnsupportedOperationException("Not supported by BasicDataSource");
 
    }


 
    public int getLoginTimeout() throws SQLException {
 
        throw new UnsupportedOperationException("Not supported by BasicDataSource");
  
    }




 
    public PrintWriter getLogWriter() throws SQLException {
        return createDataSource().getLogWriter();
    }




 
    public void setLoginTimeout(int loginTimeout) throws SQLException {
 
        throw new UnsupportedOperationException("Not supported by BasicDataSource");
 
    }



 
    public void setLogWriter(PrintWriter logWriter) throws SQLException {
        createDataSource().setLogWriter(logWriter);
        this.logWriter = logWriter;
    }





                                                           
    public boolean getRemoveAbandoned() {   
        if (abandonedConfig != null) {
            return abandonedConfig.getRemoveAbandoned();
        }
        return false;
    }                                    
                                 
     
    public void setRemoveAbandoned(boolean removeAbandoned) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setRemoveAbandoned(removeAbandoned);
        this.restartNeeded = true;
    }                                                        
                                               
       
    public int getRemoveAbandonedTimeout() { 
        if (abandonedConfig != null) {
            return abandonedConfig.getRemoveAbandonedTimeout();
        }
        return 300;
    }                                        


     
    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
        this.restartNeeded = true;
    }                                                                  
                                                             
                                                        
    public boolean getLogAbandoned() {   
        if (abandonedConfig != null) {
            return abandonedConfig.getLogAbandoned();
        }
        return false;
    }                                 

 
    public void setLogAbandoned(boolean logAbandoned) {
        if (abandonedConfig == null) {
            abandonedConfig = new AbandonedConfig();
        }
        abandonedConfig.setLogAbandoned(logAbandoned);
        this.restartNeeded = true;
    }


    //公用方法


 
    public void addConnectionProperty(String name, String value) {
        connectionProperties.put(name, value);
        this.restartNeeded = true;
    }


 
    public void removeConnectionProperty(String name) {
        connectionProperties.remove(name);
        this.restartNeeded = true;
    }

 
    public void setConnectionProperties(String connectionProperties) {
        if (connectionProperties == null) throw new NullPointerException("connectionProperties is null");


        String[] entries = connectionProperties.split(";");
        Properties properties = new Properties();
        for (int i = 0; i < entries.length; i++) {
            String entry = entries[i];
            if (entry.length() > 0) {
                int index = entry.indexOf('=');
                if (index > 0) {
                    String name = entry.substring(0, index);
                    String value = entry.substring(index + 1);
                    properties.setProperty(name, value);
                } else {
                    // no value is empty string which is how java.util.Properties works
                    properties.setProperty(entry, "");
                }
            }
        }
        this.connectionProperties = properties;
        this.restartNeeded = true;
    }





 //关闭连接池
    public synchronized void close() throws SQLException {
        closed = true;
        GenericObjectPool oldpool = connectionPool;
        connectionPool = null;
        dataSource = null;
        try {
            if (oldpool != null) {
                oldpool.close();
            }
        } catch(SQLException e) {
            throw e;
        } catch(RuntimeException e) {
            throw e;
        } catch(Exception e) {
            throw new SQLNestedException("Cannot close connection pool", e);
        }
    }


 
    public synchronized boolean isClosed() {
        return closed;
    }

 
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }


    public <T> T unwrap(Class<T> iface) throws SQLException {
        throw new SQLException("BasicDataSource is not a wrapper.");
    }
 
 



    protected static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception {
        Connection conn = null;
        try {
            conn = (Connection) connectionFactory.makeObject();
            connectionFactory.activateObject(conn);
            connectionFactory.validateConnection(conn);
            connectionFactory.passivateObject(conn);
        }
        finally {
            connectionFactory.destroyObject(conn);
        }
    }


    /**
     * Not used currently
     */
    private void restart() {
        try {
            close();
        } catch (SQLException e) {
            log("Could not restart DataSource, cause: " + e.getMessage());
        }
    }


    protected void log(String message) {
        if (logWriter != null) {
            logWriter.println(message);
        }
    }
}








  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值