代理模式本质上是利用java.lang.reflect.Proxy类中的一个静态方法:
newProxyInstance(
ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
//参数1:必须给一个加载被代理对象的类加载器,注意通常要用与当前类相同的类加载器,否则生成的代理对象在当前类中无法使用
//参数2:给一个接口数组,该数组中的所有接口将会是代理后的对象要实现的,同时也是以后通过这些接口调用代理后对象的方法(功能)
//参数3: 代理对象所有通过接口调用的方法都是通过下面的类反射方式调用的,我们可以在该反射方法中更改(拦截、增强)原型方法的功能 帮我们创建出一个代理后的对象, 用代理后的对象去执行方法,会被拦截! 具体拦截的动作(功能)
由参数三h来实现。
public class ConnUtils {
//需求:想拿到代理后的connection;改掉其中的close()函数
private static List<Connection> pool=new ArrayList<Connection>();
private static final int MAX=3;
static{
Properties p=new Properties();
try {
p.load(ConnEndUtils.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");
Class.forName(driver);
for(int i=0;i<MAX;i++){//每个connection都要被代理
final Connection con=DriverManager.getConnection(url, user, pwd);
Object proxyObj=Proxy.newProxyInstance(
ConnUtils.class.getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("close")){
//因为池循环利用;所以当调用这个函数时把connection还到池中
pool.add((Connection)proxy);
}
//其他函数原样执行
return method.invoke(con, args);
}
});
pool.add((Connection)proxyObj);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}