连接池
首先创建连接池类
@Setter
public class ConnectionPool {
/**
* 连接池(存放连接的集合)
*
*/
private LinkedList<Connection> pool = new LinkedList<>();
/**
* 连接属性
*/
private String url;
private String user;
private String password;
/**
* 池大小
*/
private Integer poolSize;
/**
* 在构造方法中初始化连接池
*/
public void init() {
for(int i=0; i<poolSize; i++) {
try {
//1.从数据库获取连接对象
Connection conn = DriverManager.getConnection(url, user, password);
//2.对连接对象创建代理
conn = createProxy(conn);
//3.将代理过的连接对象保存到池中
pool.add(conn);
} catch (SQLException e) {
throw new RuntimeException("Init connection pool error.", e);
}
}
}
/**
* 为连接对象创建代理
* @param connection
* @return
*/
private Connection createProxy(Connection connection) {
//创建回调处理器
InvocationHandler handler = new ConnectionInvocationHandler(connection, pool);
//获取连接对象的所有接口
Class<?>[] interfaces = new Class[]{Connection.class};
//获取类加载器
ClassLoader loader = ConnectionPool.class.getClassLoader();
//创建代理
connection = (Connection) Proxy.newProxyInstance(loader, interfaces, handler);
return connection;
}
/**
* 从池里面获取代理连接
* @return
*/
public Connection getConnection() {
return pool.removeFirst();
}
/**
* 查看连接池的大小
* @return
*/
public int size() {
return pool.size();
}
}
连接对象配置文件
url = jdbc:mysql://localhost:3306/city?useSSL=false
username = root
password = root
poolSize = 5
动态代理执行的回调处理器
public class ConnectionInvocationHandler implements InvocationHandler {
/**
* 目标对象(被代理的连接对象)
*/
private Connection connection;
/**
* 连接池
*/
private LinkedList<Connection> pool;
public ConnectionInvocationHandler(Connection connection,
LinkedList<Connection> pool) {
this.connection = connection;
this.pool = pool;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果当前调用的是Connection的close方法则将它放回到池中
if("close".equals(method.getName())) {
//从池的尾部放回去
//注意:这里放回池中的必须是代理对象,而不是目标Connection
pool.addLast((Connection) proxy);
return null;
} else {
//除close以外的其他方法则正常调用目标的行为
return method.invoke(connection, args);
}
}
}
配置类
配置类,将连接池放到容器中
@Slf4j
public class AppConfig {
@Value("${url}")
private String url;
@Value("${username}")
private String user;
@Value("${password}")
private String password;
@Value("${poolSize}")
private Integer poolSize;
/**
* 装配连接池
* @return
*/
@Bean
public ConnectionPool connectionPool() {
log.info("url: " + url);
log.info("user: " + user);
log.info("pwd: " + password);
log.info("size: " + poolSize);
//创建连接池并设置相关属性
ConnectionPool pool = new ConnectionPool();
pool.setUrl(url);
pool.setUser(user);
pool.setPassword(password);
pool.setPoolSize(poolSize);
//初始化连接池
pool.init();
return pool;
}
}
测试
@Slf4j
public class Main {
public static void main(String[] args) throws SQLException {
//创建容器
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
//从容器中获取连接池
ConnectionPool pool = context.getBean(ConnectionPool.class);
log.info("连接数:" + pool.size());
Connection conn1 = pool.getConnection();
Connection conn2 = pool.getConnection();
log.info("连接数:" + pool.size());
conn1.close();
conn2.close();
log.info("连接数:" + pool.size());
}
}