目的:为数据连接池中的每一个Connection创建一个代理,当需要使用Connection对象操作数据库时,先判断是否超过连接池的最大连接数,如果没有超过,取得连接,否则不进行连接。
1、抽象对象角色
JDBC提供了Connection接口
2、定义我们自己的数据连接池,实现DataSource接口
public class MyDataSource implements DataSource{
private static String url = "jdbc:mysql://localhost:3306/jdbc";
private static String user = "root";
private static String password = "";
private static int initCount = 1;
private static int maxCount = 1;
int currentCount = 0;
LinkedList<Connection> connectionsPool = new LinkedList<Connection>();
public MyDataSource() {
try {
for (int i = 0; i < initCount; i++) {
this.connectionsPool.addLast(this.createConnection());
this.currentCount++;
}
} catch (SQLException e) {
throw new ExceptionInInitializerError(e);
}
}
public Connection getConnection() throws SQLException {
synchronized (connectionsPool) {
if (this.connectionsPool.size() > 0)
return this.connectionsPool.removeFirst();
if (this.currentCount < maxCount) {
this.currentCount++;
return this.createConnection();
}
throw new SQLException("服务器连接异常");
}
}
public void free(Connection conn) {
this.connectionsPool.addLast(conn);
}
private Connection createConnection() throws SQLException {
Connection realConn = DriverManager.getConnection(url, user, password); //真实对象
MyConnectionHandler proxy = new MyConnectionHandler(this); //代理处理器
return proxy.bind(realConn); //创建代理对象
}
public Connection getConnection(String username, String password)
throws SQLException {
return null;
}
public PrintWriter getLogWriter() throws SQLException {
return null;
}
public int getLoginTimeout() throws SQLException {
return 0;
}
public void setLogWriter(PrintWriter out) throws SQLException {
}
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
3、定义动态代理处理类,实现InvocationHandler接口
class MyConnectionHandler implements InvocationHandler {
private Connection realConnection;
private Connection warpedConnection;
private MyDataSource dataSource;
private int maxUseCount = 5;
private int currentUserCount = 0;
MyConnectionHandler(MyDataSource2 dataSource) {
this.dataSource = dataSource;
}
//注意:不一定非要在该类中创建代理,只要在创建代理的时候传入一个MyConnectionHandler类的实例就可以了
Connection bind(Connection realConn) {
this.realConnection = realConn;
this.warpedConnection = (Connection) Proxy.newProxyInstance(this.realConnection .getClass().getClassLoader(), new Class[] { Connection.class },this); //创建代理对象
return warpedConnection;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!"close".equals(method.getName())) {//非关闭连接操作
this.currentUserCount++;
if (this.currentUserCount <= this.maxUseCount) //只有在这个类中进行判断后才进行连接,减轻了服务器的压力
return method.invoke(this.realConnection, args);
}else {
this.realConnection.close();
this.dataSource.currentCount--;
}
return null;
}
}