AnnotationConfigApplicationContext를 이용하여 XML 전혀 없는 standalone TCP-IP 애플리케이션을 제작하고 있습니다. 문제는 SocketServer/Client를 띄우게 되는데 커스터마이즈된 환경설정을 읽어들여 띄워야 한다는 제약조건이 있습니다.
현재 @Configuration과 @Bean, @Service의 조합을 통하여 필요한 객체들을 생성하는 데 소켓 서버를 생성하는 순서는 명확하게 기준이 있어야 합니다.
1. Configuration file을 로드한다.
2. 로드된 파일의 내용을 읽어들여 시스템 정보를 취합한다.
3. 동적인 데이터베이스 쿼리를 읽어들여 메타정보를 등록한다.
4. TCP 채널을 오픈한다.
5. 채널 오픈 후 앞서 생성된 빈들을 활용하여 초기 연결 조정작업을 수행한다.
#4, #5는 해당하는 작업은 #1, #2, #3번이 없으면 안되는 작업입니다.
@Configuration과 @Import를 이용하면 작업이 되겠지만 유연성이 scan 메소드를 통한 package 자동 빈 등록의 장점이 사라지게 되는 단점이 발생을 하네요.
스캔을 해버리면 패키지명의 순서에 따라 검색 후 빈을 등록하므로, ASCII 코드의 뒤에 해당하는 알파벳으로 시작하는 패키지의 @Component를 앞선 알파벳 패키지에서 참조하면 100% NPE가 발생을 하게 되네요.
예를 들면 org.jboss.a 패키지에서 org.jboss.b 패키지의 빈을 구동시 인젝션 시키고 싶은 경우입니다.
현재 프로젝트에서 플랫폼 리드 겸 개발자로 작업을 하고 있는데 스프링을 이용하여 컨트롤러-에이전트 구조의 TCP기반의 모니터링 솔루션 개발하고 있습니다.
객체 관리의 문제로 인하여 JBoss로 갈까도 했지만 리소스 활용적인 측면이나 비용적인 측면에서 스프링을 이용하기로 하고, 이를 통해 솔루션에 적용하고 있습니다. 문제는 기존의 2.X의 환경설정에서 탈피하여 100% 어노테이션 기반으로 클래스들을 작성하고 있는데 객체의 수명주기 부분에 막혀버렸습니다.
매뉴얼과 포럼을 찾는데 제 검색실력이 없어서인지 딱히 현재 나타나는 현상에 대한 답이 없어 결국 코딩으로 해결하는 수밖에 없었습니다.
발단은 다음과 같습니다.
1. 에이전트가 시스템의 정보를 주기적으로 수집해야 하므로 Quartz 스케줄러를 사용하여 TCP서버인 컨트롤러 측으로 수집된 데이터를 전달합니다.
2. TCP서버가 다른 문제로 인하여 연결이 종료되면, 클라이언트는 Quartz 스케줄러를 shutdown시킵니다.
3. 클라이언트가 TCP서버 재접속 시도를 계속 하다가 서버가 살아나 연결이 성립되면 스케줄러를 다시 start시킵니다.
문제는 #3인데 스케줄러가 shutdown된 상태이면 thread running상태에서 빠져나가게 되므로 재시작을 할 수 없고 다시 factory를 통해 스케줄러 인스턴스를 생성해야 하는데, 이 때 기존의 scheduler객체를 스프링의 AnnotationConfigApplicationContext의 관리 빈 대상에서 제거시키고 새롭게 스케줄러를 등록하여야 합니다.
그런데 저 빈 녀석을 어떻게 제거시켜야 하는지, BeanDefinition을 사용하여 처리해야 하는지 모르겠네요.
결국 Proxy 클래스를 만들어 Quartz Factory와 스케줄러를 핸들링하는 클래스를 스프링서비스로 등록시키고 그것을 인젝션 시켜서 사용하고 있습니다.