commons-pool源码分析总结

不论进行什么程序或者框架的源码分析,总是要建立在使用它的基础之上的,当我们使用了它,然后才会有好奇心和动力去分析它是怎么样实现的。

其实有很少的编程人员会直接使用commons-pool,但是常常在我们的项目中需要使用到它。我是如何开始接触commons-pool的呢?这是在我学习javaEE开发的时候接触的,当时候的时候需要使用dbcp作为数据库连接池,然而dbcp依赖于commons-pool来缓存连接,本人又是一个喜欢研究的人,而且喜欢对一个东西有很深的了解之后,然后将它的作用发挥到最大。

1.commons-pool提供了什么样的功能

在前面开始提到了commons-dbcp使用到了commons-pool,那么commons-dbcp为什么要使用它呢?

commons-dbcp提供给开发者一个可用的数据库连接池,顾名思义commons-dbcp缓存了很多数据库的连接。难么这个缓存的功能是在dbcp中实现的吗?不是的,其实dbcp中的数据库的缓存的功能是有commons-pool来提供的,这也就说明了commons-pool具有缓存对象的功能。

为什么需要缓存对象?这是因为对象的创建和释放都是一个很耗费时间和空间的过程,所有如果只是在需要的对象的创建对象,那么使用该对象的程序或者用户就会等待较长的时间。特别是对于需要频繁创建和销毁某类对象、或者需要频繁访问修改的应用程序来说尤为重要(当然这整个过程都是建立在可复用的对象的基础上)。

2. 缓存的基本原理

既然提到了commons-pool提供了对象缓存的功能,那么什么是对象缓存呢,以及什么是缓存呢?我们知道对象的创建的流程是:分配内存空间、对象初始化、对象注册到对象数上、返回对象的引用等过程。如果没有进行对象的缓存,那么每次需要一个对象的时候就需要经历上面的步骤,如果此类操作比较频繁,那么就会大大的降低程序的性能。

3. commons-pool缓存的实现

  • commons-pool中的泛型编程

    在java中如果要使得一段程序或者一个框架是可复用的,那么泛型编程就必不可少。泛型编程所谓的意思就是该段程序或者是框架所针对的对象的类型没有明确的限制,比如说大家常常使用的HashMap

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

    private static final long serialVersionUID = 362498820763181265L;

    /*
     * Implementation notes.
     *
     /
     ......

上面的HashMap中的K和V,没有明确的指定K和V的类型,这样就可以使得HashMap能使用多种基础的数据类型或者是自定义的类作为其的K或者V。这样就给了HashMap更灵活的使用。

而在commons-pool中则是

// 对象工厂类(T为对象的类型)
public interface PooledObjectFactory<T> {

  // 创建一个对象(T为对象的类型)
  PooledObject<T> makeObject() throws Exception;
  // 销毁一个对象(T为对象的类型)
  void destroyObject(PooledObject<T> p) throws Exception;
  ......

下面是一个小例子

UserInfo.java 这是我们需要缓存的对象的类型

package mh.test;

public class UserInfo {

    private String name;
    private int age;

    public UserInfo() {
        // TODO Auto-generated constructor stub
    }
    public UserInfo(String name, int age) {
        // TODO Auto-generated constructor stub
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "用户名:"+this.name+",年龄:"+this.age;
    }
}

UserFactory.java 缓存对象的生产工厂,必须继承commons-pool的工厂类

package mh.test;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class UserFactory implements PooledObjectFactory<UserInfo>{

    @Override
    public PooledObject<UserInfo> makeObject() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("创建一个新的对象");
        return new DefaultPooledObject<UserInfo>(new UserInfo());
    }

    @Override
    public void destroyObject(PooledObject<UserInfo> p) throws Exception {
        // TODO Auto-generated method stub

        UserInfo user = p.getObject();
        System.out.println("销毁对象"+user.toString());
        user = null;
    }

    @Override
    public boolean validateObject(PooledObject<UserInfo> p) {
        // TODO Auto-generated method stub
        if(p.getObject() instanceof UserInfo){
            System.out.println("是一个合法的对象");
            return true;
        }
        System.out.println("是一个非法的对象");
        return false;
    }

    @Override
    public void activateObject(PooledObject<UserInfo> p) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("重新初始化对象");
    }

    @Override
    public void passivateObject(PooledObject<UserInfo> p) throws Exception {
        // TODO Auto-generated method stub
        UserInfo user = p.getObject();
        System.out.println("对象已经被归还:"+user.toString());
    }

}

TestPool .java 如何使用commons-pool

package mh.test;

import org.apache.commons.pool2.impl.GenericObjectPool;

public class TestPool {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        GenericObjectPool<UserInfo> pool = new GenericObjectPool<UserInfo>(new UserFactory());
        try {
            UserInfo user = pool.borrowObject();
            user.setAge(10);
            user.setName("mh");
            System.out.println(user.toString());
            pool.returnObject(user);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}
  • commons-pool工作原理解析

其实commons-pool的工作原理很简单,泛型+工厂模式+缓存链表。泛型,可以使得框架可以缓存多种对象类型;工厂模式,用户通过继承工厂接口,并向缓冲池注册自定义的工厂类,使得框架的可扩展性更强; 缓存链表,通过链表的方式缓存已经生成好的对象。

4. 总结

  • 其实缓存的原理都是一样的,只是各自的实现的方式大同小异,只要我们了解了其中的原理之后,就能更好的去阅读源代码。
  • commons-pool提供了两种缓存服务GenericKeyedObjectPool(K,V带键值对的) 、GenericObjectPool(T,只有值的),虽然功能上有些差别,但是实现原理都是一样的。
时间: 2024-07-28 18:38:56

commons-pool源码分析总结的相关文章

Apache Commons Pool2 源码分析 | Apache Commons Pool2 Source Code Analysis

Apache Commons Pool实现了对象池的功能.定义了对象的生成.销毁.激活.钝化等操作及其状态转换,并提供几个默认的对象池实现.在讲述其实现原理前,先提一下其中有几个重要的对象: PooledObject(池对象). PooledObjectFactory(池对象工厂). Object Pool(对象池). 下面分别详细讲解它们的实现. PooledObject(池对象) 用于封装对象(如:线程.数据库连接.TCP连接),将其包裹成可被池管理的对象.提供了两个默认的池对象实现: De

mysql jdbc源码分析片段 和 Tomcat&#39;s JDBC Pool

32) Tomcat's JDBC Pool Tomcat jdbc pool的使用仅需2个jar包,分别为tomcat-jdbc.jar和tomcat-juli.jar,这两个jar包都可以在tomcat7中找到,tomcat-jdbc.jar在tomcat的lib目录下,tomcat-juli.jar在bin目录下. http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/ org.apache.tomcat.jdbc.pool

Spring Boot(3):加载DataSource过程的源码分析及yml中DataSource的配置

Spring Boot实现了自动加载DataSource及相关配置.当然,使用时加上@EnableAutoConfiguration注解是必须的.下面就是对这一部分的源码分析. (1)Spring Boot启动后会调用org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.下面是部分源码. 1 @Configuration 2 @ConditionalOnClass({ DataSource.class, E

memcache-client-forjava 源码分析之MemcachedCacheManager

接上文<memcache-client-forjava 源码分析之DefaultCacheImpl分析>,主要分析ICache另外一个针对Memcached缓存实现,重点实现了memcached的高可用能力. 由于底层访问复用了java_memcached-release包的实现,memcache-client-forjava只是在上层做了简单封装.本文重点分析下如何进行的封装,以提高自己的设计经验.个人认为,java_memcached-release源码阅读,比spymemcached更简

Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 【转】

原文地址:Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938390.html 在构架相关的汇编代码运行完之后,程序跳入了构架无关的内核C语言代码:init/main.c中的start_kernel函数,在这个函数中Linux内核开始真正进入初始化阶段, 下面我就顺这代码逐个函数的解释,但是这里并不会过于深入

spark core源码分析6 Spark job的提交

本节主要讲解SparkContext的逻辑 首先看一个spark自带的最简单的例子: object SparkPi { def main(args: Array[String]) { val conf = new SparkConf().setAppName("Spark Pi") val spark = new SparkContext(conf) val slices = if (args.length > 0) args(0).toInt else 2 val n = ma

HBase1.0.0源码分析之请求处理流程分析以Put操作为例(二)

HBase1.0.0源码分析之请求处理流程分析以Put操作为例(二) 1.通过mutate(put)操作,将单个put操作添加到缓冲操作中,这些缓冲操作其实就是Put的父类的一个List的集合.如下: private List<Row> writeAsyncBuffer = new LinkedList<>(); writeAsyncBuffer.add(m); 当writeAsyncBuffer满了之后或者是人为的调用backgroundFlushCommits操作促使缓冲池中的

[Android]Volley源码分析(四)

上篇中有提到NetworkDispatcher是通过mNetwork(Network类型)来进行网络访问的,现在来看一下关于Network是如何进行网络访问的. Network部分的类图: Network有一个实现类BasicNetwork,它有一个mHttpStack的属性,实际的网络请求是由这个mHttpStack来进行的,看BasicNetwork的performRequest()方法, 1 @Override 2 public NetworkResponse performRequest

Cordova Android源码分析系列一(项目总览和CordovaActivity分析)

PhoneGap/Cordova是一个专业的移动应用开发框架,是一个全面的WEB APP开发的框架,提供了以WEB形式来访问终端设备的API的功能.这对于采用WEB APP进行开发者来说是个福音,这可以避免了原生开发的某些功能.Cordova 只是个原生外壳,app的内核是一个完整的webapp,需要调用的原生功能将以原生插件的形式实现,以暴露js接口的方式调用. Cordova Android项目是Cordova Android原生部分的Java代码实现,提供了Android原生代码和上层We