객체에 대한 Pooling기능을 제공하는 서비스이다.객체의 생성 비용이 크고,생성 횟수가 많으면,
평균적으로 사용되는 객체의 수가 적은 경우,성능을 향상시키기 위해서 사용한다.
Object Pool은 소프트웨어 디자인 패턴으로서, 객체를 필요에 따라 생성하고 파괴하는 방식이 아닌,적절한 개수의 객체를 미리 사용
가능한 상태로 생성하여 이를 이용하는 방식이다.Client는 Pool에 객체를 요청하여 객체를 얻은 후, 업무를 수행한다.
얻어온 객체를 이용하여 업무 수행을 끝마친 후, 객체를 파괴하는 것이 아니라 Pool에게 돌려주어 다른 Cliet가 사용할 수 있도록 한다.
Object Pooling은 객체 생성 비용이 크고,객체 생성 횟수가 많으며,평균적으로 사용되는 객체의 수가 적은 경우,높은 성능의 향상을 가져다 준다.
ObjectPool은 아래와 같은 interface이다.
public interface ObjectPool { Object borrowObject(); void returnObject(Object borrowed); }
ObjectPool interface를 구현하여 코드를 작성하여 사용한다.
ObjectPool을 구현한 추상 클래스이다.
public abstract class BaseObjectPool implements ObjectPool { public abstract Object borrowObject() throws Exception; public abstract void returnObject(Object obj) throws Exception; public abstract void invalidateObject(Object obj) throws Exception; public int getNumIdle() throws UnsupportedOperationException { return -1; } public int getNumActive() throws UnsupportedOperationException { return -1; } public void clear() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } public void addObject() throws Exception, UnsupportedOperationException { throw new UnsupportedOperationException(); } public void close() throws Exception { closed = true; } public void setFactory(PoolableObjectFactory factory) throws IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } protected final boolean isClosed() { return closed; } protected final void assertOpen() throws IllegalStateException { if(isClosed()) { throw new IllegalStateException("Pool not open"); } } private volatile boolean closed = false; }
METHOD | 설 명 |
---|---|
borrowObject | 객체 할당 |
returnObject | 객체 반환 |
invalidateObject | 객체 할당시 유효성검사 |
getNumIdle | Idle 상태 객체수 리턴 |
getNumActive | Active 상태 객체수 리턴 |
clear | 객체 삭제 |
addObject | Pool에 객체 추가 |
setFactory | PoolableObjectFactory를 구현한 객체 설정 |
isClosed | 객체 close여부 판단 |
assertOpen | 객체가 사용가능한 상태판단 |
KeyedObjectPool은 이기종(異機種) 객체들로 구성된 pool 구현을 위한 interface
public interface KeyedObjectPool { Object borrowObject(Object key); void returnObject(Object key, Object borrowed); }
METHOD | 설 명 |
---|---|
borrowObject | 객체 할당 |
returnObject | 객체 반환 |
org.apache.commons.pool package는 Object Pool객체 생성과 pool로부터 생성되는 object의 created와 destoryed 부분을 분리하여 구현 할 수 있도록 지원한다. PoolableObjecFactory는 pooled object의 생존주기 관리를 위한 interface이다.
public interface PoolableObjectFactory { Object makeObject(); void activateObject(Object obj); void passivateObject(Object obj); boolean validateObject(Object obj); void destroyObject(Object obj); }
METHOD | 설 명 |
---|---|
makeObject | 객체 생성 |
activateObject | Pool로 부터 객체를 할당 받을때 호출된다(재초기화 할때 이용). |
passivateObject | Pool로 객체를 반환할 때 호출된다(초기화 할때 이용). |
validateObject | 객체가 유호한지 측정하기 위해 호출된다. |
destroyObject | 객체를 삭제할떄 호출된다. |
ObjectPool 구현한 프로그램은 PoolableObjectFactory를 구현한 프로그램을 받아드리도록 구현한다면, 다양하고 독특한 ObjectPool을 구현 할 수 있다.
PoolableObjecFactory를 구현한 추상클래스이다.
public abstract class BasePoolableObjectFactory implements PoolableObjectFactory { public abstract Object makeObject() throws Exception; /** No-op. */ public void destroyObject(Object obj) throws Exception { } /** * This implementation always returns <tt>true</tt>. * @return <tt>true</tt> */ public boolean validateObject(Object obj) { return true; } /** No-op. */ public void activateObject(Object obj) throws Exception { } /** No-op. */ public void passivateObject(Object obj) throws Exception { }
KeyedObjectPools를 위한 PoolableObjecFactory이다.
public interface KeyedPoolableObjectFactory { Object makeObject(Object key); void activateObject(Object key, Object obj); void passivateObject(Object key, Object obj); boolean validateObject(Object key, Object obj); void destroyObject(Object key, Object obj); }
METHOD | 설 명 |
---|---|
makeObject | 객체 생성 |
activateObject | Pool로 부터 객체를 할당 받을때 호출된다(재초기화 할때 이용). |
passivateObject | Pool로 객체를 반환할 때 호출된다(초기화 할때 이용). |
validateObject | 객체가 유호한지 측정하기 위해 호출된다. |
destroyObject | 객체를 삭제할떄 호출된다. |
KeyedPoolableObjectFactory를 구현한 추상클래스이다.
public abstract class BaseKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory { public abstract Object makeObject(Object key) throws Exception; /** No-op. */ public void destroyObject(Object key, Object obj) throws Exception { } /** * This implementation always returns <tt>true</tt>. * @return <tt>true</tt> */ public boolean validateObject(Object key, Object obj) { return true; } /** No-op. */ public void activateObject(Object key, Object obj) throws Exception { } /** No-op. */ public void passivateObject(Object key, Object obj) throws Exception { } }
<bean id="dbcpObjectpool" class="egovframework.rte.fdl.objectpool.dbcp.dbcpObjectpoolset"> <property name="pool" ref="dbcpObjectPooler" /> </bean> <bean id="dbcpObjectPooler" class="egovframework.rte.fdl.objectpool.dbcp.DbcpObjectpool"/>
PARAMETER | 설 명 |
---|---|
pool | egovframework.rte.fdl.objectpool.dbcp.DbcpObjectpool |
DbcpObjectpool.java는 org.apache.commons.dbcp package를 사용하여 만든 가이드프로그램이다. Source설명은 중요부분을 나누어서 하겠다.
import org.apache.commons.dbcp.ConnectionFactory; import org.apache.commons.dbcp.DriverManagerConnectionFactory; import org.apache.commons.dbcp.PoolableConnectionFactory; import org.apache.commons.dbcp.PoolingDriver; import org.apache.commons.pool.impl.GenericObjectPool;
org.apache.commons.dbcp package를 import한다.
int maxActive = 1; byte whenExhaustedAction = 2; long maxWait = 1000; int maxIdle = 2; int minIdle = 1; boolean testOnBorrow = true; boolean testOnReturn = true; long timeBetweenEvctionRunsMillis = 600000; int numTestsPerEvictionRun = 5; long minEvictableIdleTimeMillis = 3600000; boolean testWhileIdle = true;
ObjectPool 생성시 사용할 정보를 설정하는 필드를 정의한다.
설 정 | 설 명 |
---|---|
maxActive | 커넥션 풀이 제공할 최대 커넥션 개수 |
whenExhaustedAction | 커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정한다. |
maxWait | 사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수. 음수일 경우 제한이 없다. |
maxIdle | 사용되지 않고 풀에 저장될 수 있는 최소 커넥션 개수. |
testOnBorrow | true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사한다. |
testOnReturn | true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사한다. |
timeBetweenEvctionRunsMillis | 사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정한다. |
numTestsPerEvictionRun | 사용되지 않는 커넥션을 몇 개 검사할지 지정한다. |
minEvictableIdleTimeMillis | 사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출한다. |
testWhileIdle | true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거한다. |
private void loadProperties() throws IOException { String fileName_ = Thread.currentThread().getContextClassLoader().getResource("jdbc.properties").getFile(); Properties props = null; FileInputStream fis = null; props = new Properties(); fis = new FileInputStream(fileName_); props.load(new BufferedInputStream(fis)); fis.close(); g_Driver = props.getProperty("driver"); g_URL = props.getProperty("dburl"); g_User = props.getProperty("username"); g_Password = props.getProperty("password"); }
jdbc.properties를 통해서 데이타베이스 접속정보를 얻어온다.
private void setupDriver(String driver,String url,String user,String password)throws Exception { Class.forName(driver); GenericObjectPool connectionPool = new GenericObjectPool(null); connectionPool.setMaxActive(maxActive); connectionPool.setMaxIdle(maxIdle); connectionPool.setMaxWait(maxWait); connectionPool.setWhenExhaustedAction(whenExhaustedAction); connectionPool.setMinIdle(minIdle); connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvctionRunsMillis); connectionPool.setTestOnBorrow(testOnBorrow); connectionPool.setTestOnReturn(testOnReturn); connectionPool.setTestWhileIdle(testWhileIdle); connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url,user,password); PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, false, true); PoolingDriver poolingDriver = new PoolingDriver(); poolingDriver.registerPool("database", connectionPool); }
위에서 정의한 설정정보를 GenericObjectPool(ObjectPool)를 생성한 후 각각 해당 메소드를 호출하여 설정한다. PoolableObjectFactory를 구현한 PoolableConnectionFactory를 사용하였다.
DbcpObjectpoolTest.java은 가이드프로그램을 이용한 테스트 프로그램이다.
@Resource(name = "dbcpObjectPooler") private DbcpObjectpool pool; /** * Object pool 테스트 모듈 * @see 개발프레임웍크 실행환경 개발팀 */ @Test public void runModule() { Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; String sql = "select * from emp"; try { con = pool.getConnection(); pstmt = con.prepareStatement(sql); rs = pstmt.executeQuery(); logger.debug("module1"); while(rs.next()) { logger.debug(rs.getString("ename")); } }catch(Exception e) { e.printStackTrace(); }finally { pool.freeConnection(con, pstmt,rs); } }