[回收机制] Evictor - "空闲对象的驱逐者"定时器任务，继承自TimerTask

public void run()：运行对象池维护线程。
驱逐对象具有驱逐者的资格，同时保证空闲实例可用的最小数量。
因为调用"驱逐者线程"的定时器是被所有对象池共享的，但对象池可能存在不同的类加载器中，所以驱逐者必须确保采取的任何行为都得在与对象池相关的工厂的类加载器下。
[回收机制] BaseGenericObjectPool<T> - 为"可配置的对象池"提供通用的功能

此类存在的主要原因是减少两个对象池实现的重复代码。

public final void setTimeBetweenEvictionRunsMillis(long
timeBetweenEvictionRunsMillis)：设置"空闲对象的驱逐者线程"间隔运行之间的休眠毫秒数。（同时，会立即启动"空闲对象的驱逐者线程"）
如果该值是非正数，没有"空闲对象的驱逐者线程"将运行。
默认是 -1，即没有"空闲对象的驱逐者线程"在后台运行着。
上一层入口：GenericObjectPool.setConfig(GenericObjectPoolConfig)
顶层入口：GenericObjectPool.GenericObjectPool(PooledObjectFactory,GenericObjectPoolConfig)，在最后还会调用startEvictor(long)来再次启动"空闲对象的驱逐者线程"。
这样在初始化时，这里创建的"驱逐者线程"就多余了，会立刻被销毁掉。
但这里为什么要这样实现呢？
我的理解是：为了能动态更新"驱逐者线程"的调度间隔时间。

final void startEvictor(long delay)：启动"空闲对象的驱逐者线程"。
当该方法被调用时，有一个驱逐者线程运行着，则会停止它并使用一个新的驱逐者线程替换它。

public abstract void evict() throws
Exception：执行numTests个空闲池对象的驱逐测试，驱逐那些符合驱逐条件的被审查对象。
如果testWhileIdle为true，则被审查的对象在访问期间是有效的(无效则会被删除)；
否则，仅有那些池对象的空闲时间超过minEvicableIdleTimeMillis会被删除。

abstract void ensureMinIdle() throws Exception：试图确保配置的对象池中可用空闲实例的最小数量。