好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

DBCP数据库连接池原理分析

    这里有DBCP的一些配置参数,通过这些参数可以大致知道其原理是怎么样的?

 

  初始化为0大小的对象池,当需要Connection对象时,此时 当前总共连接对象小于maxActivity,空闲连接数小于maxldle,则创建一个连接对象(使用池对象工厂),当Connection的数量达到最大活跃数的时候,则进行等待,直到有可用的连接或者到达maxWait抛出异常。

   例如在 tomcat 中,利用 JNDI 来查找到资源 javax.sql.DataSource 的实现,如果使用 dbcp 连接池,则该实现为 org.apache.commons.dbcp.BasicDataSource 。我们可以从这个称为 “ 数据源 ” 的类中调用 getConnection 方法来获得与数据库的连接。但内部是如何实现的呢?对象池在其中占据什么位置呢?这一切对于外部使用者来说是透明的。  

BasicDataSource 的 getConnection 首先建立了 PoolingDataSource 对象来 getConnection 。这个 PoolingDataSource 对象中引用了 ObjectPool ,在 getConnection() 时,是从 ObjectPool 中借用了一个对象,既调用 ObjectPool.borrowObject() 方法。而对于熟悉 commons-pool 的程序员来说, ObjectPool 肯定有与之对应的 Factory 创建对象,并放到池中。因此 dbcp 通过实现了接口 org.apache.commons.pool.PoolableObjectFactory 的类 org.apache.commons.dbcp.PoolableConnectionFactory 的 makeObject 方法来创建连接 Connection 对象。然而 PoolableConnectionFactory 持有对 ConnectionFactory 的引用, ConnectionFactory 可以有 3 种策略来创建 Connection 对象。其中 DriverConnectionFactory 调用了数据库厂商提供的 Driver 来获得 Connection 。

   数据库连接池的原理和线程池的原理很像,可以结合理解。

这里有一个细节使用完成之后,他是如何将对象放入对象池呢?通过调用Close方法,你也许会疑问,这不是进行对象的销毁吗?确实,但是原代码中使用了反射 的动态代理的技术,在运行时修改了close方法。

    

//获取连接的方法
    private Connection getConnection()
    {
        
        try {
            //获取一个连接
            final Connection conn=DriverManager.getConnection(url, user, password);
            
            //把连接交给动态代理类转换为代理的连接对象
            Connection myconn = (Connection)Proxy.newProxyInstance(
                    MyPool.class.getClassLoader(), 
                    new Class[] {Connection.class}, 
                             //编写一个方法处理器
                    new InvocationHandler() {
                
                @Override
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    Object value = null;
                    
                    //当遇到close方法,就会把对象放回连接池中,而不是关闭连接
                    if(method.getName().equals("close"))
                    {
                        MyPool.connList.addLast(conn);
                    }else
                    {
                        //其它方法不变
                        value = method.invoke(conn, args);
                    }
                    return value;
                }}
            );    
            return myconn;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


DBCP数据库连接池原理分析

标签:

查看更多关于DBCP数据库连接池原理分析的详细内容...

  阅读:38次