dependency injection을 사용하십시오.
Spring Framework은 매우 유용한 소프트웨어이고 내 개인적으로 좋아하지만 Google Guice과 같은 많은 대안이 있습니다.
Spring을 사용하면 언어별로 하나씩 2 개의 (3 개, 15 개 ...) 별도의 컨텍스트를 정의하고 적절한 컨텍스트에서 필요한 구성 요소를 얻을 수 있습니다. 두 번째 방법과 비슷하지만 Language
클래스를 사용하지 않아야합니다. 예를 들면 다음과 같습니다.
또 다른 대안은 단일 컨텍스트를 사용하지만 bean ID에 사용자의 언어를 접두사로 사용하는 것입니다."English-Tokenizer"및 "Chinese-Tokenizer"가 있습니다.
이전에 의존성 삽입을 사용한 적이없는 경우 공장 및/또는 동적 클래스 로딩을 통해 얻을 수있는 결과에 대해 너무 많은 작업처럼 들릴 수 있습니다 .-) 그러나 그렇지 않습니다. (구성 요소의 속성/종속성을 구성 할 수 있으므로 자신의 싱글 톤 등을 캐싱하거나 유지하는 것에 대해 걱정할 필요가 없습니다.) 일단 사용을 시작하면 사용하지 않은 채로 어떻게 살아 왔는지 궁금 할 것입니다. -)
업데이트 (두 번째 의견에서 질문에 대답).
다음은 샘플 "ComponentLocator"패턴입니다. ComponentLocator
은 Spring에 의존성이없는 싱글 톤입니다. 인스턴스 (및 구현)는 컨텍스트에 의해 주입됩니다. ComponentLocator
의
public abstract class ComponentLocator {
protected static ComponentLocator myInstance;
protected abstract <T> T locateComponent(Class<T> componentClass, String language);
public static <T> T getComponent(Class<T> componentClass, String language) {
return myInstance.locateComponent(componentClass, language);
}
}
구현은 인터페이스 이름은 세미콜론 및 언어 (예를 들어, "영어 com.mypackage.Parser") 다음과 같이 맥락에서 콩의 이름을 지정하는 가정합니다. ComponentLocatorImpl은 컨텍스트에서 bean으로 선언되어야합니다 (bean 이름은 중요하지 않음). 다른 코드에서
public class ComponentLocatorImpl extends ComponentLocator
implements ApplicationContextAware {
private ApplicationContext myApplicationContext;
public void setApplicationContext(ApplicationContext context) {
myApplicationContext = context;
myInstance = this;
}
@Override
protected <T> T locateComponent(Class<T> componentClass, String language) {
String beanName = componentClass.getName() + ":" + language;
return componentClass.cast(myApplicationContext.getBean(beanName, componentClass));
}
}
당신이 ApplicationContext
를로드 할거야 (의() 주?) : 당신이 실제로 직접 다른 곳에서 컨텍스트를 참조 할 필요가 없습니다
ApplicationContext ctx = new ClasspathXmlApplicationContext("components.xml");
주 응용 프로그램. 위의 단지 하나의 가능한 방법입니다
Parser englishParser = ComponentLocator.getComponent(Parser.class, "English");
Parser chineseParser = ComponentLocator.getComponent(Parser.class, "Chinese");
참고 그것을 당신이 상황에서 당신의 언어 별 클래스를 가하고 거의 유일한 걸 가정합니다 : 당신이 당신의 구성 요소를 얻을 필요가 어디든지 당신은 않습니다. 귀하의 경우에는 아마도 (모든 언어를 동시에 사용할 수 있어야하기 때문에) 가장 좋을 것입니다. 그렇지 않으면 모든 수업 (언어 당 한 번)이 복제되므로 A/B/C 문제가 여기에 해당되지 않을 수 있습니다. 당신은 당신이 할 수있는 것은 A/B/C 의존성이있는 경우
는하지만 (나는 A, B, C를 믿고있어 인터페이스이며, Aimpl는 Bimpl, Cimpl 자신의 구현입니다) :
<bean id="A" class="Aimpl">
<property name="B" ref="B"/>
</bean>
<bean id="B" class="Bimpl">
<property name="C" ref="C"/>
</bean>
<bean id="C" class="Cimpl">
<property name="tokenizer" ref="Tokenizer:English"/>
</bean>
구현에는 setB(), setC() 및 setTokenizer() 메소드가 있어야합니다. 후자도 가능하지만 이것은 생성자 주입보다 쉽습니다.
감사합니다. DI 개념에 대한 기사를 읽었지만 아직 사용하지 않았습니다. 그러나 나는 그것에 대해 몇 가지 질문을 가지고있다 : i) 나는 그 콩들이 클래스의 ctor에 인수를 전달하기 위해 구성 될 수 있다고 가정한다. ii) 런타임에 "응용 프로그램 컨텍스트"(시스템에서 사용하는 언어)를 변경할 수 있으며 DI로 그렇게 할 수 있는지 궁금합니다. iii) 캐싱을 사용하면 englishContext.getBean ("Parser")를 두 번 호출하면 두 번째 캐싱은 항상 캐시 된 버전을 반환한다는 것을 의미합니다. iv) 전체 프레임 워크 대신 Spring의 IoC 컨테이너를 사용할 수 있습니까? –
1) "제작자에게 인수를 전달"하는 것이 무슨 뜻인지 잘 모르겠습니다. 컨텍스트에서 bean 자체에 대한 특성 (또는 생성자 인수)을 지정할 수 있습니다. 2) 언어 별 컨텍스트를 사용하는 경우 ApplicationContext 인스턴스 세트가 있고 적절한 컨텍스트에서 빈 (예 : 파서)을 가져올 수 있습니다. 컨텍스트 자체는 필요할 때 런타임에 쉽게 다시로드 할 수 있습니다. 3) 기본적으로 yes입니다. 하지만 원하는 것이 아니라면 빈 범위를 변경하여 항상 새로운 인스턴스를 반환 할 수 있습니다. 4) 물론입니다. 필요한 모듈 (및 JAR) 만 선택할 수 있습니다. – ChssPly76
예, 저는 생성자 인수를 말했습니다. 고마워요. 나는 확실히 DI를 시도해야한다고 생각합니다. 최종 질문 : (코드에서) 일반적으로 ApplicationContext를 저장하고 .getBean() 메소드를 호출하는 곳은 어디입니까? 당신을 돕기 위해 어떤 종류의 도우미 클래스가 있습니까? 또한 클래스 'C'를 생성하는 클래스 B를 생성하는 클래스'A '가 있고'Tokenizer '를 가져와야하는 클래스'C'가 있다고 가정 해 보겠습니다. 이 경우 DI를 사용하려면 'A', 'B'및 'C'의 생성자를 변경하여 'Tokenizer'를 인수로 사용하고 'A'에 주입하여 순서대로 처리해야합니다. 다른 수업을 듣기 위해? –