有时候,仅仅简单的把池中的所有对象都当成一类对象并不能解决所有问题,有时候我们需要根据一些参数比如key值去查找某些指定的池中对象,比如可以根据一个参数来决定使用池中具体的那一个数据库连接,等等。此时就需要使用KeyedPoolableObjectFactory和KeyedObjectPool接口。
一个Connection类,可以想象成一个远程连接比如数据库连接等。其中包括创建连接,关闭连接,和一个print方法。
package com.googlecode.garbagecan.commons.pool.sample2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyConnection {
private static Logger logger = LoggerFactory.getLogger(MyConnection.class);
private String name;
private boolean connected;
public MyConnection(String name) {
this.name = name;
}
public void connect() {
this.connected = true;
logger.info(name + ": " + connected);
}
public void close() {
this.connected = false;
logger.info(name + ": " + connected);
}
public boolean isConnected() {
return this.connected;
}
public String getName() {
return this.name;
}
public void print() {
logger.info(this.name);
}
}
一个KeyedPoolableObjectFactory接口的实现类,提供makeObject, activateObject, passivateObject, validateObject, destroyObject方法。
package com.googlecode.garbagecan.commons.pool.sample2;
import org.apache.commons.pool.KeyedPoolableObjectFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyConnectionKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
private static Logger logger = LoggerFactory.getLogger(MyConnectionKeyedPoolableObjectFactory.class);
private static int count = 0;
public Object makeObject(Object key) throws Exception {
MyConnection myConn = new MyConnection(key.toString());
logger.info(myConn.getName());
myConn.connect();
return myConn;
}
public void activateObject(Object key, Object obj) throws Exception {
MyConnection myConn = (MyConnection)obj;
logger.info(myConn.getName());
}
public void passivateObject(Object key, Object obj) throws Exception {
MyConnection myConn = (MyConnection)obj;
logger.info(myConn.getName());
}
public boolean validateObject(Object key, Object obj) {
MyConnection myConn = (MyConnection)obj;
logger.info(myConn.getName());
return myConn.isConnected();
}
public void destroyObject(Object key, Object obj) throws Exception {
MyConnection myConn = (MyConnection)obj;
logger.info(myConn.getName());
myConn.close();
}
}
最后是一个测试类package com.googlecode.garbagecan.commons.pool.sample2;
import org.apache.commons.pool.KeyedObjectPool;
import org.apache.commons.pool.impl.StackKeyedObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Test {
private static Logger logger = LoggerFactory.getLogger(Test.class);
public static void main(String[] args) throws Exception {
MyConnectionKeyedPoolableObjectFactory factory = new MyConnectionKeyedPoolableObjectFactory();
KeyedObjectPool pool = new StackKeyedObjectPool(factory);
try {
logger.info("================================================");
for (int i = 0; i < 10; i++) {
String key = "conn_" + i;
MyConnection myConn = (MyConnection)pool.borrowObject(key);
try {
myConn.print();
} catch(Exception ex) {
pool.invalidateObject(key, myConn);
} finally {
pool.returnObject(key, myConn);
}
}
logger.info("================================================");
for (int i = 0; i < 10; i++) {
String key = "conn_xxx";
MyConnection myConn = (MyConnection)pool.borrowObject(key);
try {
myConn.print();
} catch(Exception ex) {
pool.invalidateObject(key, myConn);
} finally {
pool.returnObject(key, myConn);
}
}
} finally {
logger.info("Close Pool");
try {
pool.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
运行测试类,可以看到在第一个循环里虽然循环了10次,一共要了10次MyConnection对象,每次请求的key都不一样,从conn_0到conn_9,由于使用的是KeyedPoolableObjectFactory和KeyedObjectPool接口,所以返回的10个MyConnection对象实例每个都不一样,并且从日志可以看出makeObject方法被调用了10次。第二个循环里,虽然也是请求了10次MyConnection对象,但是由于每次的key都不一样,所以每次返回的都是同一个MyConnection对象实例,并且从日志可以看出makeObject方法只被调用了一次。