手写java连接池高级版(动态代理)
- 首先要明白所有连接池(数据源)都实现jdk提供的接口,实现这个规范后就可以在spring容器中都可以使用.已经测试过,百万计数据访问没有出问题,动态代理实现.
- 如果spring框架中使用,spirng.xml配置如下:
<bean id="dataSource" class="com.oracle.datesource.MyDateSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
<property name="username" value="c##user"></property>
<property name="password" value="123456"></property>
<property name="maxSize" value="30"></property>
</bean>
- 使用jdc提供的动态代理,需要实现一个接口,所以我们需要定义一个Connection适配器,代码如下:
package com.oracle.datesource;
import java.sql.Connection;
public interface MyConnection extends Connection{
}
- 连接池代码如下:
package com.oracle.datesource;
import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import javax.sql.DataSource;
public class MyDateSource implements DataSource {
public String driverClassName;
private String url;
private String username;
private String password;
private Integer maxSize = 100;
private final static Object obj = "lock";
private List<Connection> conns = Collections.synchronizedList(new ArrayList<>());
public MyDateSource() {
}
public void init() {
try {
Class.forName(driverClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException("驱动未找到");
}
for (int i = 0; i < maxSize; i++) {
try {
conns.add(DriverManager.getConnection(url, username, password));
} catch (SQLException e) {
throw new RuntimeException("连接出错!");
}
}
}
@Override
public Connection getConnection() throws SQLException {
synchronized (obj) {
if (conns.size() == 0) {
try {
obj.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
Connection proxyConn = null;
try {
Connection conn = conns.remove(0);
proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(),
MyConnection.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj1 = null;
if (method.getName().equals("close")) {
conns.add(conn);
obj.notifyAll();
} else {
obj1 = method.invoke(conn, args);
}
return obj1;
}
});
} catch (IndexOutOfBoundsException e) {
System.out.println("连接超时!");
} catch (Exception e) {
e.printStackTrace();
}
return proxyConn;
}
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return getConnection();
}
public void close() {
for (Connection connection : conns) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
System.gc();
System.out.println("已关闭所有连接!!");
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setMaxSize(Integer maxSize) {
this.maxSize = maxSize;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public void setLogWriter(PrintWriter arg0) throws SQLException {
}
@Override
public void setLoginTimeout(int arg0) throws SQLException {
}
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
return false;
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
return null;
}
}