본문 바로가기

Java

Jrebel Ibatis Plugin을 만들어 봅시다.. -1-

회사에서 jrebel을 사용하면서
ibatis 에서 사용하는 sqlMap.xml과 Domain 클래스들의 변경에 대한 이슈가 있어서
플러그인을 만들었습니다.

회사에서는 프레임웍이 있어서 순수 ibatis를 위한 플러그인은 아니라서
소스를 그대로는 못 보여드리고..
순수 ibatis (2.3.x)에서 사용 가능한 ibatis 플러그인을 한번.. 의사 코드를 사용해서
만들어 보려고 합니다.

우선 jrebel의 플러그인은 이미 컴파일된 클래스의 바이트 코드에
원하는 코드를 끼워넣어서
thread를 가로채는 방식으로 원하는 메서드를 먼저 실행하거나
나중에 실행하도록 하는 것이 기본적인 구현 방식입니다.

기본적으로 ibatis를 사용 할 때는

이런식이 됩니다.

일반적으로 매번 저렇게 SqlMapClient를 build하지 않고 was 구동시나 초기화 단계해서 sqlMapClient를 생성해 놓고
가져다가 쓰는 방식을 사용 할 것 입니다. 최초 초기화는 SqlMapXmlCache의 init()메서드에서 실행한다고 가정하고 초기화 단계에서 초기화 된 SqlMapClient를 SqlMapXmlCache라는 클래스의 getSqlMapClient(); 메서드를 사용해 가져와서 쿼리를 수행한다고 가정 하겠습니다. 즉,

이런식이 되겠지요....


만들려고 하는  플러그인의 컨셉은 이렇습니다.

쿼리를 실행하기 위해서 위 SqlMapXmlCahce.getSqlMapClient()의 메서드가 호출 되는 순간을 캐치하여
저 메서드 호출 전에 sqlMap.xml 파일들의 변경 여부를 체크하여, 변경된 xml이 있으면 SqlMapClientBuilder.buildSqlMapClient(reader); 메서드를 실행하여 xml을 다시 로딩하는 것 입니다.

(엄격히 얘기하면 캐치한다기 보다는 그냥 컴파일 된 클래스에 끼워 넣는다고 하는 것이  맞는 것 같습니다.)

단, Ibatis에서는 최초 xml 로딩시 내부에서 resultMap 클래스로 사용된 클래스들을 static Map에 캐시하여 놓고 사용
하기 때문에, 만약에 resultMap으로 사용된 Domain 클래스에 필드가 추가되거나 하는 것들은 buildSqlMapClient 메서드를
통해 초기화 하더라도 ibatis에서 인식하지 못 하게 됩니다.


따라서, resultMap으로 사용된 클래스가 jrebel에 의해 다시 로딩되었다면, 그 클래스를 ibatis의 캐시에서 지워버리는
부분이 추가적으로 필요합니다.

이 부분은 jrebel sdk에 있는 인터페이스 ClassEventListener 를 사용하여 처리해보도록 하겠습니다.