2010-12-10 4 views
30

와 클래스의 수집과 나는 다음과 같은 구조를 가지고 :주입 내가 구글 Guice 2.0 일을 주입하기 위해 노력하고있어 Guice

ActionLibrary (List<Action> theActions) 
: 나는 다음 생성자를 가진 ActionLibrary이

FooAction implements Action 
BarAction implements Action 

Guice에서 ActionLibrary의 인스턴스를 요청하면 Guice가 등록 된 Action 클래스 (FooAction, BarAction)를 모두 식별하여 생성자에 전달하도록합니다. 여기서 세 번째 액션 BazAction을 추가하면 모듈에 등록하는 것만 큼 간단하며 생성자의 목록에 자동으로 추가됩니다.

이것이 가능합니까?

답변

38

원하는 것은 Multibindings입니다. 특히, 당신은 Set<Action> 바인딩 할 (안 List을하지만, Set 당신이 정말로 어쨌든 원하는 아마도)이 같은 :

Multibinder<Action> actionBinder = Multibinder.newSetBinder(binder(), Action.class); 
actionBinder.addBinding().to(FooAction.class); 
actionBinder.addBinding().to(BarAction.class); 

이 그럼 당신은 어디서나 Set<Action>@Inject 수 있습니다.

+1

'List'가 실제로 필요하다면 어떨까요?'Collection '? – jilt3d

+2

'List '는 이해가되지 않습니다. 왜냐하면'Multibinder'의 전체 개념은 여러 모듈로부터 바인딩을 수집한다는 것이고, 아이템에 대한 신뢰할 수있는 사용자 정의 순서가 없기 때문입니다. 특정 순서로 항목이있는'List'가 정말로 필요하다면, 직접 그 목록을 만들고 직접 바인딩하는 것이 합리적입니다. 그러나 'Multibinder'의 일반적인 사용 사례는 인터페이스의 여러 구현을 바인딩하는 것이고,이 경우 일반적으로 순서는 중요하지 않으며 동일한 것을 하나 이상 원하지는 않습니다. – ColinD

20

내가 여러 가지로 묶는 것의 더 좋은 방법이라고 생각하는 것을 보여 드리겠습니다. Action을 플러그 할 수있게하고 다른 사람이 추가 할 수있게하려면 Multibinder을 인스턴스화해야하는 숨기기를 누군가가 사용할 수 있도록 간단하게 Module을 제공하는 것이 유용합니다. 여기 예가 있습니다 :

public abstract class ActionModule extends AbstractModule { 
    private Multibinder<Action> actionBinder; 

    @Override protected void configure() { 
    actionBinder = Multibinder.newSetBinder(binder(), Action.class); 
    configureActions(); 
    } 

    /** 
    * Override this method to call {@link #bindAction}. 
    */ 
    protected abstract void configureActions(); 

    protected final LinkedBindingBuilder<Action> bindAction() { 
    return actionBinder.addBinding(); 
    } 
} 

왜 이렇게 좋은가? 누군가가 어디서나 ActionModule을 사용하여 표준 바인딩 API를 통해 Action을 더 추가 할 수 있습니다. 나는 그것이 더 가독하다고 생각한다.

public final class MyStandardActionModule extends ActionModule() { 
    @Override protected void configureActions() { 
    bindAction().to(FooAction.class); 
    bindAction().to(BarAction.class); 
    // If you need to instantiate an action through a Provider, do this. 
    bindAction().toProvider(BazActionProvider.class); 
    // You can also scope stuff: 
    bindAction().to(MySingletonAction.class).in(Singleton.class); 
    } 
} 

multibinder을 숨기기 위해 Module를 사용하는이 패턴은 Guice 코드에 사용되는 : 다음은 사용 예입니다. 조금 앞을 내다 보지만 일은 깨끗하게 유지합니다. 필요한 경우 MapBinder과 유사한 작업을 수행 할 수도 있습니다. 원하는만큼 많은 ActionModule을 인스턴스화 할 수 있습니다.

+0

이 방법에 대해 더 이상 궁금한 점이 있으면 알려 주시기 바랍니다. - ... 구성 자료 라이브러리를 작성하는 데 매우 편리합니다. – Tom

+0

매우 깨끗하고 간단한 접근! +1 –