手搓一个数据库连接池
继承DataSource
接口
public interface FateDataSourceInterface extends DataSource {
@Override
default Connection getConnection() throws SQLException{
return null;
}
@Override
default Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
default <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
default boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
default PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
default void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
default void setLoginTimeout(int seconds) throws SQLException {
}
@Override
default int getLoginTimeout() throws SQLException {
return 0;
}
@Override
default Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
编写一个抽象类注入数据库连接信息
public abstract class AbstractFateDataSource implements FateDataSourceInterface {
private String url;
private String username;
private String password;
private String driver;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public Connection getConnection() throws SQLException {
return getConnection(username, password);
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return doConnect(username, password);
}
private Connection doConnect(String username, String password) throws SQLException {
return DriverManager.getConnection(url, username, password);
}
}
采用动态代理实现对数据库连接的代理
public class ConnectionProxy implements InvocationHandler {
private Connection realConnection;
private Connection proxyConnection;
private FateDataSource dataSource;
public ConnectionProxy(Connection realConnection, FateDataSource dataSource) {
this.realConnection = realConnection;
this.dataSource = dataSource;
this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(),new Class<?>[]{Connection.class},this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if ("close".equals(methodName)){
dataSource.closeConnection(this);
return null;
}else {
return method.invoke(realConnection, args);
}
}
public Connection getRealConnection() {
return realConnection;
}
public void setRealConnection(Connection realConnection) {
this.realConnection = realConnection;
}
public Connection getProxyConnection() {
return proxyConnection;
}
public void setProxyConnection(Connection proxyConnection) {
this.proxyConnection = proxyConnection;
}
public FateDataSource getDataSource() {
return dataSource;
}
public void setDataSource(FateDataSource dataSource) {
this.dataSource = dataSource;
}
}
编写抽象类实现类
public class FateDataSource extends AbstractFateDataSource{
private final List<ConnectionProxy> idleConnections = new ArrayList<>();
private final List<ConnectionProxy> activeConnections = new ArrayList<>();
private int poolMaxActiveConnections=10;
private int poolMaxIdleConnections=5;
private long poolMaxToWait= 30000L;
private final Object monitor = new Object();
public FateDataSource() {
}
public FateDataSource(int poolMaxActiveConnections, int poolMaxIdleConnections, long poolMaxToWait) {
this.poolMaxActiveConnections = poolMaxActiveConnections;
this.poolMaxIdleConnections = poolMaxIdleConnections;
this.poolMaxToWait = poolMaxToWait;
}
@Override
public Connection getConnection() throws SQLException {
ConnectionProxy connectionProxy = getConnectionProxy(super.getUsername(),super.getPassword());
return connectionProxy.getProxyConnection();
}
private ConnectionProxy getConnectionProxy(String username, String password) throws SQLException {
Boolean wait = false;
ConnectionProxy connectionProxy=null;
while (connectionProxy==null){
synchronized (monitor){
if (!idleConnections.isEmpty()){
connectionProxy=idleConnections.remove(0);
}else {
if (activeConnections.size()<poolMaxActiveConnections){
connectionProxy = new ConnectionProxy(super.getConnection(username, password), this);
}
}
}
if (!wait){
wait = true;
}
if (connectionProxy==null){
try {
monitor.wait(poolMaxToWait);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
if (connectionProxy!=null){
activeConnections.add(connectionProxy);
}
return connectionProxy;
}
public void closeConnection(ConnectionProxy connectionProxy){
synchronized (monitor){
activeConnections.remove(connectionProxy);
if (idleConnections.size()<poolMaxIdleConnections){
idleConnections.add(connectionProxy);
}
monitor.notify();
}
}
}