apache-commons 池化技术
池化技术
!!!info 羽化而登仙,池化而提效 本篇文章我们的研究专题是池化技术, 其实所谓池化可以简单理解为缓存。将那些创建比较耗时的对象,缓存起来,放到一个池子里。 比如数据库连接池,线程池,字符串常量池。这个技术常用于框架类设计。本文教你基于Apache-commons-pool2快速实现一个常量池的设计。 !!!
一、Pool2 四大件

1.1 新建资源

1.2 回收资源

二、数据库连接池实战
我们利用Common Pool2工具 可以使用很少的代码就实现了池化的能力。
2.2 构建连接工厂
可以看到核心方法非常少,开发者只用实现很少方法即可
- makeObject 创建资源
- activateObject 资源被激活时候调用
- passivateObject 资源在回收时候调用
- validateObject 当配置了资源检查时候会在创建和回收时候调用
- destroyObject 资源在销毁时候调用
java
1public class PooledConnectFactory implements PooledObjectFactory<Connection> {
2
3
4 /**
5 * 数据库连接
6 */
7 private final String url;
8
9 /**
10 * 用户名
11 */
12private final String userName;
13
14 /**
15 * 数据密码
16 */
17private final String password;
18
19public PooledConnectFactory(String url, String userName, String password) {
20 this.url = url;
21this.userName = userName;
22this.password = password;
23}
24
25 /**
26 * 对象被激活后,会进行调用
27 *
28 * @param pooledObject a {@code PooledObject} wrapping the instance to be activated
29 */
30 @Override
31 public void activateObject(PooledObject<Connection> pooledObject) throws Exception {
32 }
33
34 /**
35 * 销毁数据库连接
36 *
37 * @param pooledObject a {@code PooledObject} wrapping the instance to be destroyed
38 * @throws Exception 异常
39 */
40 @Override
41 public void destroyObject(PooledObject<Connection> pooledObject) throws Exception {
42 Connection connection = pooledObject.getObject();
43connection.close();
44}
45
46 /**
47 * 创建一个数据库连接
48 *
49 * @return 数据库连接的池对象包装
50 * @throws Exception 异常
51 */
52 @Override
53 public PooledObject<Connection> makeObject() throws Exception {
54 Connection connection = DriverManager.getConnection(this.url, this.userName, this.password);
55return new DefaultPooledObject<>(connection);
56}
57
58 /**
59 * 回收资源时候进行调用
60 * @param pooledObject a {@code PooledObject} wrapping the instance to be passivated
61 *
62 * @throws Exception
63 */
64 @Override
65 public void passivateObject(PooledObject<Connection> pooledObject) throws Exception {
66
67 }
68
69 @Override
70 @SneakyThrows
71 public boolean validateObject(PooledObject<Connection> pooledObject) {
72 Connection connection = pooledObject.getObject();
73// 如果连接关闭说明已经失效就返回false告诉池子,已经失效,会自动移除
74 return !connection.isClosed();
75}
76}2.3 连接池演示
java
1 @Test
2 @DisplayName("验证回收对象")
3 public void testReturn()throws Exception{
4 // 1. 构建一个数据连接池化工厂
5 String dbUrl = "jdbc:mysql://127.0.0.1:3306/test";
6String user = "root";
7String pass = "123456";
8PooledConnectFactory pooledConnectFactory = new PooledConnectFactory(dbUrl, user, pass);
9
10// 2. 给池子添加支持的配置信息
11 GenericObjectPoolConfig<Connection> config = new GenericObjectPoolConfig<Connection>();
12// 2.1 最大池化对象数量
13 config.setMaxTotal(5);
14// 2.2 最大空闲池化对象数量
15 config.setMaxIdle(2);
16// 2.3 最小空闲池化对象数量
17 config.setMinIdle(2);
18// 2.4 间隔多久检查一次池化对象状态,驱逐空闲对象,检查最小空闲数量小于就创建
19 config.setTimeBetweenEvictionRuns(Duration.ofSeconds(5));
20// 2.5 阻塞就报错
21 config.setBlockWhenExhausted(true);
22// 2.6 最大等待时长超过5秒就报错,如果不配置一直进行等待
23 config.setMaxWait(Duration.ofSeconds(5));
24// 2.7 是否开启jmx监控,默认开启
25 config.setJmxEnabled(true);
26// 2.8 一定要符合命名规则,否则无效
27 config.setJmxNameBase("org.apache.commons.pool2:type=MysqlConnObjectPool,name=ConnectJmxNameBase");
28// 生成数据库连接池
29 // 连接池配置最大5个连接setMaxTotal(5),但是获取6次,那么有一次获取不到就会阻塞setBlockWhenExhausted(true),
30 // 当等待了10秒setMaxWait(Duration.ofSeconds(10))还是获取不到。就直接报错
31 try (GenericObjectPool<Connection> connPool = new GenericObjectPool<>(pooledConnectFactory, config)) {
32 for (int i = 1; i <= 7; i++) {
33 Connection connection = connPool.borrowObject();
34Statement statement = connection.createStatement();
35ResultSet show_tables = statement.executeQuery("show tables");
36printRows("Connect-" + i + ">", show_tables);
37connPool.returnObject(connection);
38}
39 }
40 }甚至还能配置支持jmx管理。非常的简单和方便。
