2017-02-12 5 views
1

В Guice, когда вы указываете время жизни определенного экземпляра, вы будете использовать аннотацию с областью обзора, например bind(Applebees.class).in(Singleton.class);. Или вы, кажется, быть в состоянии использовать экземпляры области видимости какРазница между аннотацией области охвата и экземплярами области видимости в Guice

bind(UserPreferences.class) 
     .toProvider(UserPreferencesProvider.class) 
     .in(ServletScopes.REQUEST); 

И официально Guice рекомендует прежний подход, потому что прежний подход позволяет повторно использовать класс модуля. Но я не уверен в этом. Мое предположение такое, поэтому, пожалуйста, проверьте, правильно ли это.

Примерами экземпляров являются термины Servelet, поэтому, если вы используете экземпляры области видимости вместо аннотаций для области видимости, класс модуля применим только к Servelet. С другой стороны, если вы используете аннотации для области видимости, вы можете повторно использовать свой класс модуля, если не откажетесь от Guice.

Итак, это право? Не могли бы вы проверить?

ответ

0

Я считаю, что ваше понимание верное, но есть небольшая тонкость в отношении того, какое повторное использование будет затронуто.

Вы, вероятно, имея в виду этот текст от the Guice wiki on Scopes (курсив мой):

Предложение in() принимает либо обзорное аннотацию, как RequestScoped.class, а также Scope случаях, как ServletScopes.REQUEST:

bind(UserPreferences.class) 
    .toProvider(UserPreferencesProvider.class) 
    .in(ServletScopes.REQUEST); 

примечание является предпочтительным, поскольку оно позволяет повторно использовать модуль в различных типах приложений. Например, объект @RequestScoped может быть привязан к HTTP-запросу в веб-приложении и RPC, когда он находится на сервере API.

Даже с сервлетов конкретных областей Guice, вы можете выбрать между экземпляром Scope ServletScopes.REQUEST и @RequestScoped annotation, и выбирать между in(Scope scope) и in(Class scopeAnnotation) соответственно (см ScopedBindingBuilder). Почти каждая область должна иметь соответствующую аннотацию, поскольку они особенно полезны для классов и методов @Provides.

Важно осознать, что есть всегдаScope instance, что на самом деле реализует поведение обзорного (в частности, обертывания незаданного поставщика, так что он может вернуться уже возвращены экземплярами в правильных условиях). Чтобы связать аннотацию с экземпляром Scope, вам необходимо убедиться, что модуль вызывает bindScope, который принимает класс аннотации Scope и экземпляр Scope; для сервлетов, Guice has this binding automatically installed via InternalServletModule.

@Override 
protected void configure() { 
    bindScope(RequestScoped.class, REQUEST); 
    bindScope(SessionScoped.class, SESSION); 
    // ... 
} 

Так что преимущество использования in(Class scopeAnnotation)? При привязке к экземпляру Scope вы указываете Guice точно, какой экземпляр Scope вы хотите использовать, вместо того, чтобы позволить пользователю использовать bindScope, чтобы связать аннотацию с другим экземпляром Scope. В примере, который я выделил выше, вы можете представить, используя тот же модуль, не используя фактические расширения сервлетов Guice (кроме аннотаций), но это возможно только при привязке к классам аннотаций, а затем вызовите bindScope самостоятельно. Если вы связываете с помощью in(Scope), вам нужно будет изменить эту строку или написать новый модуль.

Это особенно важно для ваших собственных экземпляров настраиваемой области и аннотации, поскольку она позволяет изменить свое поведение Scoping последовательно через приложение:

@Override public void configure() { 
    // BAD: To change the scope, you'll need to change three lines. 
    // If you don't change all three together, you'll get inconsistent behavior. 
    bind(A.class).to(AImpl.class).in(MyScope.INSTANCE); 
    bind(B.class).to(BImpl.class).in(MyScope.INSTANCE); 
    bindScope(AScoped.class, MyScope.INSTANCE); 
} 

@Override public void configure() { 
    // GOOD: To change the scope, you can change one line, and optionally 
    // extract that line to a separate Module. 
    bind(A.class).to(AImpl.class).in(AScoped.class); 
    bind(B.class).to(BImpl.class).in(AScoped.class); 
    bindScope(AScoped.class, MyScope.INSTANCE); 
}