Late Binding in Java
참조 : http://neilbartlett.name/blog/osgibook/
OOP의 목적 중 하나는 의존성을 최대한 낮춰서 코드의 재사용성과 유연함을 늘리는 것이다.
자바에서는 인터페이스를 사용해서 이런 목적에 접근 했다. 인터페이스는 불편하고 그것을 구현한 구현체만 바꾸면 인터페이스를 사용하고 있는 클라이언트 코드는 변경할 필요가 없었기 때문이다. 하지만, 한계가 있는데, 객체를 생성하려면 어차피 구현한 클래스를 클라이언트 쪽에서 알고 있어야 한다는 것이다.
그래서, 스캐너의 생성자를 사용해서 문자열을 받고 그 문자열로 분기문을 돌려서 구현체를 기반으로 객체를 만드는 코드를 사용하기도 하는데, 역시나 새로운 구현체가 생기거나 하면, 또 코드를 바꿔야 된다.
이에 대한 대안으로 스캐너를 사용하지 않고, "다른 뭔가"가 그 객체를 제공해주게 하는 것이다. 그래서 등장한게 "Assembler" 다. "Assembler"를 여러 곳에서 만들어 쓰다가 패턴이 발견되었고, 그 패턴을 구현한 프레임워크가 스프링과 구글쥬스다.
이 들을 Dependency Injection 프레임워크라고 한다. (물론 스프링은 그게 전부는 아니지만) 불행히도, 이런 Assembler Pattern도 정적이라는 특성 때문에 몇 가지 문제가 있다. 객체들의 연관 관계를 정적으로 한 번 생성하고 말기 떄문에, 객체 생성 순서를 신경 써야 한다. B가 A 객체를 참조하려면 A 객체를 먼저 만들어야 된다. 그리고 객체간에 상호 참조(Circular Dependency)도 조심해야 된다.
또 다른 문젠 동적으로 업데이트 하는 것이 불가능하다. 이렇게 정적으로 묶여있는 의존성 그래프에는, 아주 작은 객체 연관 관계를 변경하려고 해도 전체 시스템을 껐다가 켜야 한다.
OSGi는 바로 이 문제를 동적인 "서비스"를 이용해서 해결한다.
서비스는 DI 프레임워크에서의 빈 처럼 평번한 자바 객체(POJO)다. 서비스는 하나 이상의 인터페이스 이름으로 OSGi 서비스 레지스트리에 의해 제공된다. 서비스는 다른 서비스를 사용할 수 있고 고정적인 그래프로 묶이는게 아니라, 서비스는 언제든지 동적으로 등록되고 해지될수 있다. 따라서 서비스들 사이의 관계는 임시적인 관계이다.
객체 생성 순서 문제는 다음과 같이 해결한다. B가 A를 필요로 하는 상황에서 B 객체를 만들 때 A 객체가 있는지 화인하고 안 만들어져있으면 이 객체를 이용할 수 있을 때 까지 잠시 대기한다. 그리고 A 객체를 B가 이용하고 있는 도중에 A가 사라지고 새로운 A' 객체를 등록하면 서비스 B한테 이벤트를 날려서 교체하게 해준다.
인터페이스 -> Scanner -> Assembler -> DI Framework -> OSGi