• DBCP数据库连接池原理分析


     在比较大的项目中,需要不断的从数据库中获取数据,Java中则使用JDBC连接数据库,但是获取数据库的连接可是相当耗时的操作,每次连接数据库都获得 、销毁数据库连接,将是很大的一个开销。为了解决这种开销,则使用了对象池的技术。程序启动时,先创建一定数量的数据库连接对象,然后只要一用到就直接从对象池中取出连接对象,然后使用完成后不对其销毁,而是再返回到对象池中,这样使连接池对象能反复使用,虽然增加了启动时所需要的时间但是提高了响应速度,对象池也相当于是一个缓存。

        这里有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);  
            }  
        }  
  • 相关阅读:
    师生关系
    2019-2020-1 20191213兰毅达《信息安全专业导论》第九周学习总结
    2019-2020 20191213 《信息安全专业导论》第八周学习总结
    2019-2020学年 20191213兰毅达《信息安全导论》第七周学习总结
    2019-2020 20191213《信息安全专业导论》第五周学习总结
    2019-2020《信息安全专业导论》第四周学习总结
    2019-2020学年 20191217《信息安全专业导论》第三周学习总结
    师生关系
    2019-2020 20191213《信息安全专业导论》第二周学习总结
    《计算机概论》速读提问
  • 原文地址:https://www.cnblogs.com/novalist/p/6560805.html
Copyright © 2020-2023  润新知