2012-07-14 3 views
2

내 라이브러리 코드에서 나중에 Class.forName()을 사용하여 인스턴스를 생성하기 위해 JAXB를 사용하여 XML 파일에서 클래스 이름을로드합니다. Class.forName()을 사용하여 클래스를로드하는 다른 방법이 있습니까?

public void libraryMethod() throws Exception { 
    List<String> classNames = loadClassNamesFromXML(); 

    for (String className : classNames) { 
    Class.forName(className).newInstance().doThings(); 
    } 
} 

지금, 어떤 사용자가 응용 프로그램을 구성은 OSGi를 사용하고, 그들이 내 XML 구조를 사용하여 구성한 클래스는 다른 클래스 로더 내 라이브러리를로드 : 가상의 예는 사건을 설명하기 위해. 클래스를 찾을 수 없으므로로드가 실패 할 수 있습니다.

더 많은 신뢰할 수있는 방법으로 이러한 클래스를로드 할 수 있습니까? 또는이 인스턴스를 구성하는 다른 방법이 있습니까? 나는이 결과 제안을 열려있어 :

public void libraryMethod() throws Exception { 
    // Spring does things like this: 
    List<SomeType> instances = loadInstancesFromXML(); 

    for (SomeType instance : instances) { 
    instance.doThings(); 
    } 
} 

일부 제약 : 도서관 관점에서

  • 을, 그 인스턴스의 수명주기는 중요하지 않습니다. 사용자 (사용자)가있는 경우 내 라이브러리는 알 수 없습니다.
  • 저는이 라이브러리에서 간단하게 작업하기를 원하므로 Spring과 같은 구성 프레임 워크에 대한 외부 종속성을 피하기를 원합니다. 따라서 표준 JDK 6+ 배포판으로 얻을 수있는 솔루션에만 관심이 있습니다.
  • 저는 간단한 XML 구성 파일을 유지하고 싶습니다 (XML 구조에 대한 약간의 수정은 괜찮습니다).
+1

당신은 해결하려고하는 실제 문제를 보여주지 않고 이미 아주 특별한 해결책을 가지고 있습니다. xml 구성에서 무엇을하는지 설명하고 패키지를 가져 오지 않고 다른 번들의 클래스를로드해야하는 이유는 무엇입니까? –

+0

@ChristianSchneider : 도서관 ([jOOQ] (http://www.jooq.org))을 작성합니다. 임의의 사용자 패키지를 가져올 수는 없지만 라이브러리 사용자가 내 라이브러리에'SomeType' 구현을 삽입 할 수있게하고 싶습니다. 스프링을 사용하면 그러한 구현을 쉽게 삽입 할 수 있지만 내 라이브러리가 스프링 자체에 "많이"종속 될 수 있음을 의미합니다. –

+0

질문을하기 전에 조사를 해보십시오. (게으른 시작) – Pawan

답변

4

라이브러리가 유연하고 OSGi 및 비 OSGi 환경에서 작동하도록하려면 사용자가 자신의 ClassLoader를 제공하거나 라이브러리에 클래스 이름을 알려주도록 허용해야합니다. Neil Bartlett blog post을 읽으십시오.

+0

Neil이 궁극적 인 권위자이기 때문에 이유가 없습니다. 더 자세히 토론하기 :-) 그가 결론을 내리면, 추측을 그만 두십시오. –

1

JDBC4 드라이버에는 ServiceProvider 메커니즘을 사용하여 드라이버 구현을 JVM에 등록하는 JAR 파일에 META-INF/services/java.sql.Driver가 포함되어 있습니다 (java.util.ServiceLoader javadocs 참조). 드라이버를 클래스 경로에두면 드라이버가 자동으로 등록되므로 Class.forName을 사용할 필요가 없습니다. 대신 앱 코드는 ServiceLoader.load를 사용하여 등록 된 드라이버를 검색합니다. 동일한 구성이 다른 구성에 사용될 수 있습니다. 아마도 그와 비슷한 것을 사용할 수 있을까요? 제쳐두고, 자신의 구현을 서비스 제공자 메커니즘에 등록 할 때, spi과 같은 주석을 사용하는 것이 매우 편리해 보인다.

+0

예. ServiceProvider는 Service Registry에서 또 다른 손상된 패러디입니다. 그러나 100 % OSGi가 옵션이 아니면 ServiceProvider는 아무 것도없는 것보다 낫습니다. 하지만 클래스 로더는 도움이되지 않습니다. –

+0

@IvanDubrov : 흥미 롭습니다. ServiceProvider를 사용한다면 "클래스 로딩 문제"가 무엇인지 설명해 주시겠습니까? –

+0

OSGi에서 깨진 ThreadContext 클래스 로더를 사용하거나 명시 적으로 단일 클래스 로더를 제공해야하지만 OSGi에서는 서비스를 제공하는 여러 번들이있을 수 있으므로 여러 클래스 로더가 있습니다. –

2

설명해 주셔서 감사합니다. Spring은 OSGi에서 이것을 더 쉽게 만들지 않을 것이다. 가져 오지 않는 패키지의 구현 클래스를 삽입 할 수는 없습니다. OSGi에서는 일반적으로 OSGi 서비스를 사용하여 번들 외부에서 시작하여 컴파일시 알려지지 않은 구현을 주입합니다.

그래서 사용자는 사용자가 지정한 인터페이스를 구현하고 구현을 OSGi 서비스로 게시합니다. 그런 다음 모든 서비스를 선택하거나 사용자가 xml 구성에서 자신의 서비스에 대한 LDAP 필터를 지정할 수있게 할 수 있습니다.

이 aproach의 장점은 클래스를로드하고 클래스 로더를 신경 쓸 필요가 없다는 것입니다. 그래서 이것은 OSGi에서 권장되는 방법입니다. 내부와 외부에서 동일한 솔루션을 원한다면 OSGi Ivan의 클래스 로더 + 클래스 이름을 지정하는 방법이 대안입니다.

+0

그 설명에 감사드립니다. Spring이 해결책이 될 수 있다고 생각한 이유는 jOOQ/OSGi에 문제가있는 특정 사용자가 [jOOQ] (http://www.jooq.org)를 구축하고 아마 패치를 적용했기 때문입니다. 그러나 이것이 일반적으로 작동하지 않는다는 것을 아는 것이 좋다. LDAP는 잔인한 소리처럼 들리지만 서비스는 좋은 생각 일 수 있습니다. @ MarkoTopolnik의 컨텍스트 클래스 로더가 해결 방법으로 작동했지만 사용자 정의 클래스 로더를 지정할 수있는 옵션이 지금까지는 가장 좋은 옵션 인 것 같습니다. –

+0

OSGi에서 제공하는 서비스를 필터링하면 LDAP 구문에서 필터를 사용할 수 있습니다. 이것은 모든 OSGi 프레임 워크에서 사용할 수있는 특별한 것이 아닙니다. 서비스를 게시 한 사용자는 속성을 제공 할 수 있으며 서비스를 검색하는 사용자는 속성에서 이러한 필터를 사용하여 검색합니다. aproach 서비스를 사용한다면 클래스 로더가 필요 없지만 OSGi에 의존하게됩니다. –

2

일반적으로 OSGi에서는 서비스를 사용해야합니다. Class.forName/XML 구성이 너무 인기있는 이유는 단일 클래스 만 제어 할 수 있기 때문입니다. 나머지를 구성하려면 초기화/호출 할 클래스를 알아야합니다.

OSGi에서는 각 모듈 (번들)이 선언적 서비스 (또는 활성자를 통해 기존 방식으로)를 제어 할 수 있으므로이 문제는 존재하지 않습니다. 따라서 OSGi에는 피어 투 피어 모델이 있습니다. 누구나 서비스를 등록하고 다른 서비스에 의존 할 수 있습니다.

따라서 클래스 이름을 지정하지 않고 클래스 이름을 전역 적으로 고유하다고 가정하면 (대형 시스템에 있지 않음) 서비스를 사용하고 Java 컴파일러를 떠나기가 훨씬 쉽습니다. 이 클래스 이름은 오류가 발생하기 쉽습니다. 일반적으로 이는 클라이언트를 초기화 할 필요가 없으므로 서비스를 등록하고 전화를 기다리는 경우가 많음을 의미합니다. 그러나, 화이트 보드 패턴 주소는 (bndtools 및 BND 주석과) 고객에 대해 알고 싶은 상황 :

"서버"

@Component 
public class MyLib { 
    @Reference(type='*') 
    void addSomeType(SomeType st) { 
     st.doThings(); 
    } 
} 

클라이언트

@Component 
public class MyClient implements SomeType { 
    public void doThings() { ... } 
} 

희망 이것은 도움이됩니다.

+0

그것은 흥미 롭습니다. 그러나 OSGi를 사용하지 않는 라이브러리 사용자도이 기능을 통해 이익을 얻을 수 있어야하므로 내 라이브러리에 OSGi를 너무 많이 소개하고 싶지는 않습니다. –

+0

사실, jooq를 보면 아마 인생을 원할 것입니다. _extender_ 패턴을 더 모듈화하고 지원합니다. OSGi에서는 활성화 된 번들을 추적하는 것이 쉽지 않다. –

관련 문제