/*动态代理, 技术入口: java.lang.reflect包中,
Object proxiedObj = Proxy.newProxyInstance(...)
*/
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
//数据库连接池---v3---用户直接调用con.close()就可以实现还回池中---采用动态代理模式增强conn
public class Conn4Utils {
//创建一个池
private static List<Connection> pool = new ArrayList<Connection>();
private static final int NUM=3;
static{
try {
//读取资源文件 properties
Properties p = new Properties();
//当资源文件放在classpath下 ----用类加载器读
p.load(Conn4Utils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String user = p.getProperty("username");
String pwd = p.getProperty("password");
for(int i=0;i<NUM; i++){
final Connection conn = DriverManager.getConnection(url, user, pwd);//原型对象
//利用动态代理模式,把conn改成它的代理后的对象conn2放入池中,同时在代理拦截中把close()方法拦截并做成把它还回池中的动作
Object proxiedObj = Proxy.newProxyInstance(
Conn4Utils.class.getClassLoader(),
//conn.getClass().getInterfaces(), //坑:不能替代下一行,因为mysql中使用了自己的类加载器
new Class[]{Connection.class},
new InvocationHandler() {//回调函数,通过代理后的对象执行的所有方法(接口中有的)都会自动进入这个方法来实现"所调方法的功能"
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {//proxy即是proxiedObj
//把close方法拦截并更改成把“代理后的对象”放回池中的动作
if("close".equals( method.getName()) ){
pool.add( (Connection)proxy );
System.out.println("往池中还回来一个连接。。。");
return null; //跳过下面的放行,这样原有的close()功能就没了
}
return method.invoke(conn, args); //放行
}
});
Connection conn2 = (Connection) proxiedObj;
pool.add(conn2);
//pool.add((Connection) proxiedObj); //代替上面两行
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static synchronized Connection getConn(){
if(pool.size()<=0){
System.out.println("池中已经没有了,请稍候再连");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConn();
}
System.out.println("从池中拿走一个...");
return pool.remove(0);
}
}