使用jdbc实现自定义连接池
1.初级版
- 定义一个LinkedList集合,作为连接池的容器,因为在使用连接池容器时会出现大量的增删改查的情况,所以这里使用LinkedList集合来当做容器
- 在静态代码块中初始化一批链接
public class MyDataSource {
private static LinkedList<Connection> pools = new LinkedList<>();
static {
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < 5; i++) {
String url = "jdbc:mysql://localhost:3306/spring_db?useSSL=false";
Connection connection = DriverManager.getConnection(url, "root", "");
pools.add(connection);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public Connection getCon(){
Connection connection = pools.removeFirst();
return connection;
}
public void addBack(Connection connection){
pools.addLast(connection);
}
public static int size(){
return pools.size();
}
}
2 进阶版
- 因为在提供方法获取链接时,我们的命名方式不是很规范,这时我们可以使用sun公司给我们提供的接口,对接口中的方法进行实现,有利于规范方法名,
- 实现DataSource接口
public class MyDataSource implements DataSource {
private static LinkedList<Connection> pools = new LinkedList<>();
static {
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < 5; i++) {
String url = "jdbc:mysql://localhost:3306/spring_db?useSSL=false";
Connection connection = DriverManager.getConnection(url, "root", "");
pools.add(connection);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void addBack(Connection connection){
pools.addLast(connection);
}
public static int size(){
return pools.size();
}
@Override
public Connection getConnection() throws SQLException {
Connection connection = pools.removeFirst();
return connection;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
3 终极版
- 在回收链接时,我们需要使用addBack方法才可以将链接回收到连接池中
- 我们可以对Connection对象的close方法使用动态代理实现增强,来达到close时不会销毁链接,而是将链接归还到连接词中
public class MyDataSource implements DataSource {
private static LinkedList<Connection> pools = new LinkedList<>();
static {
try {
Class.forName("com.mysql.jdbc.Driver");
for (int i = 0; i < 5; i++) {
String url = "jdbc:mysql://localhost:3306/spring_db?useSSL=false";
Connection connection = DriverManager.getConnection(url, "root", "");
pools.add(connection);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static int size(){
return pools.size();
}
@Override
public Connection getConnection() throws SQLException {
Connection connection = pools.removeFirst();
ClassLoader classLoader = connection.getClass().getClassLoader();
Class<?>[] interfaces = connection.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("close")){
pools.addLast(connection);
return null;
}else {
Object invoke = method.invoke(connection, args);
return invoke;
}
}
};
Connection proxy = (Connection) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
return proxy;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
4 总结
- 其实就是对jdbc的一些操作进行封装,达到类似C3P0的效果
- 在对connection方法的增强时为什么使用代理模式而不是装饰者设计模式,是因为装饰者设计模式在对实现相同的接口时,要把所有的方法都实现,而使用代理模式时,我们就可以对接口中的一个方法进行增强即可,不必重写接口中的所有方法
- 这也是代理模式比装饰者设计模式好的一个地方,可以使代码量减小,使代码更简洁