前言
通过对象池编写一个数据库连接池,深入学习,巩固对象池用法。
能代替其它数据库连接池产品
- Hikari、DBCP、Tomcat、Druid…
带监控,随时了解了解连接池的情况
ConnectionPooledObjectFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public class ConnectionPooledObjectFactory implements PooledObjectFactory<MyConnection> { private ObjectPool<MyConnection> objectPool;
public ObjectPool<MyConnection> getObjectPool() { return objectPool; }
public void setObjectPool(ObjectPool<MyConnection> objectPool) { this.objectPool = objectPool; }
@Override public PooledObject<MyConnection> makeObject() throws Exception { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection( "jdbc:mysql://localhost:3306/xxxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true", "root", "root123" ); MyConnection myConnection = new MyConnection(); myConnection.setConnection(connection); myConnection.setObjectPool(objectPool); return new DefaultPooledObject<>(myConnection); }
@Override public void destroyObject(PooledObject<MyConnection> p) throws Exception { p.getObject().close(); }
@Override public boolean validateObject(PooledObject<MyConnection> p) { Connection connection = p.getObject(); try { PreparedStatement statement = connection.prepareStatement("SELECT 1"); ResultSet resultSet = statement.executeQuery(); int i = resultSet.getInt(1); return i == 1; } catch (SQLException e) { return false; } }
@Override public void activateObject(PooledObject<MyConnection> p) throws Exception { }
@Override public void passivateObject(PooledObject<MyConnection> p) throws Exception { MyConnection myConnection = p.getObject(); Statement statement = myConnection.getStatement(); if (statement != null) { statement.close(); } } }
|
MyDataSource
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| public class MyDataSource implements DataSource { private GenericObjectPool<MyConnection> pool;
public GenericObjectPool<MyConnection> getPool() { return pool; }
public void setPool(GenericObjectPool<MyConnection> pool) { this.pool = pool; }
public MyDataSource() { ConnectionPooledObjectFactory factory = new ConnectionPooledObjectFactory(); this.pool = new GenericObjectPool<>(factory); factory.setObjectPool(pool); }
@Override public Connection getConnection() throws SQLException { try { return this.pool.borrowObject(); } catch (Exception e) { throw new SQLException("获取连接失败!", e); } }
@Override public Connection getConnection(String username, String password) throws SQLException { return this.getConnection(); }
@Override public <T> T unwrap(Class<T> iface) throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public boolean isWrapperFor(Class<?> iface) throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public PrintWriter getLogWriter() throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public void setLogWriter(PrintWriter out) throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public void setLoginTimeout(int seconds) throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public int getLoginTimeout() throws SQLException { throw new UnsupportedOperationException("不支持的操作!"); }
@Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new UnsupportedOperationException("不支持的操作!"); } }
|
MyConnection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
public class MyConnection implements Connection { private Connection connection; private Statement statement; private ObjectPool<MyConnection> objectPool; @Override public Statement createStatement() throws SQLException { return this.connection.createStatement(); }
@Override public PreparedStatement prepareStatement(String sql) throws SQLException { PreparedStatement prepareStatement = this.connection.prepareStatement(sql); this.statement = prepareStatement; return prepareStatement; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { PreparedStatement statement = this.connection.prepareStatement(sql, columnNames); this.statement = statement; return statement; } @Override public void close() throws SQLException { if (this.isClosed()) { try { objectPool.invalidateObject(this); } catch (Exception e) { throw new SQLException(e); } } else { try { objectPool.returnObject(this); } catch (Exception e) { this.connection.close(); throw new SQLException(e); } } } }
|
如何使用?
1 2 3 4 5
| @Bean @Primary public DataSource dataSource(){ return new DMDataSource(); }
|
如何使用 spring-boot-starter-actuator
添加监控?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Endpoint(id = "datasource") public class DataSourceEnpoint { private MyDataSource dataSource;
public DataSourceEnpoint(MyDataSource dataSource) { this.dataSource = dataSource; }
@ReadOperation public Map<String, Object> pool() { GenericObjectPool<MyConnection> pool = dataSource.getPool(); HashMap<String, Object> map = Maps.newHashMap(); map.put("numActive", pool.getNumActive()); map.put("numIdle", pool.getNumIdle()); map.put("createdCount", pool.getCreatedCount()); return map; } }
|