2014-02-08 3 views
3

Я хотел бы иметь переменную области с переменной весной. В Guice это очень просто:переменная сеанса или запроса переменной весна

@Singleton 
class MyBean 
{ 
    @Inject @Named("session-scoped") 
    private Provider<Integer> someString; 
    void doSomething() 
    { 
     // returns a random number for a current session. 
     // Each user session should generate new number, 
     // but one session should keep the same number. 
     Integer n1 = someString.get(); 
     Integer n2 = someString.get(); 
     assert n1 == n2; 
    } 
} 
... 
class MyModule extends AbstractModule 
{ 
    @Override 
    protected void configure() 
    { 
    ... 
    } 

    @Provides 
    @SessionScoped 
    @Named("session-scoped") Integer someString() 
    { 
     return new Random().nextInt(); 
    } 
} 

Как я могу сделать что-то подобное весной?

Имейте в виду, что это java.lang.Integer, а не какой-либо пользовательский компонент, он не может быть проксированным.

ответ

0

В вашем случае вам не нужна область сеанса. Вам просто нужен одноплодный обычай экземпляр поставщика

interface CustomProvider<E> { 
    public E get(); 
} 

@Configuration 
class TestConfig { 
    @Bean 
    public CustomProvider<Integer> factory() { 
     return new CustomProvider<Integer>() { 
      @Override 
      public Integer get() throws BeansException { 
       return new Random().nextInt(); 
      } 
     }; 
    } 
} 

и впрыснуть его

@Inject 
private CustomProvider<Integer> factory; 

я пропустил, что вы хотели такое же значение для сессии. See Emerson's answer for that.


В целом для сессии бобы: область действия

@Configuration В классе, вы можете предоставить @Bean метод, который имеет объем сеанса.

@Bean 
@Scope(value = WebApplicationContext.SCOPE_SESSION /* or simply "session" */) 
public SomeBean someBean() { 
    return new SomeBean(); 
} 

Вы можете использовать @Scope аннотацию на @Component аннотированный класса, а также.

В XML

<bean id="someBean" class="com.example.SomeBean" scope="session" /> 
+0

А как его использовать? Не могли бы вы указать точку инъекции? Имейте в виду, что это 'java.lang.String', а не SomeBean, он не может быть проксирован. – kan

+0

@kan А я этого не видел. Позвольте мне вернуться к вам. –

+0

@kan Я думаю, что это лучшее, что вы можете сделать. Совпадает с тем, что вы делаете в Guice. –

0
@Component 
@Scope("session") 
public class IntegerProvider implements Provider<Integer> { 

    private Integer value = new Random().nextInt(); 

    public Integer get() { 
     return this.value; 
    } 
} 

...

@Autowired 
private Provider<Integer> integerProvider; 

...

assert this.integerProvider.get().equals(this.integerProvider.get(); 
+0

Это лучшее, что я сделал сам уже, но я вынужден кэшировать значение в Провайдере ... В более сложном сценарии - значение вычисляется из других инъецированных bean-компонентов, я не мог выполнить инициализацию в конструкторе, это выглядит хуже, я необходимо добавить многопоточность безопасности. – kan

+0

Похоже, что ваша модель домена недостаточно сильна. Спросите себя: «Что означают эти значения?» «Почему они заняты сеансом?» «Как они связаны?» и т. д. Если вы можете моделировать их как объект сущности (http://martinfowler.com/bliki/EvansClassification.html), вы можете сделать этот объект bean-компонентом с областью сеанса, ввести его туда, где вам это нужно, и позволить другим фазам мутировать Это. –

+0

Мне не нравится, что Spring настолько навязчив, что он диктует, как мне проектировать модель домена. На данный момент это всего лишь кешированный параметр, если становится яснее, как это должно быть в модели домена, я реорганизую его, но из-за весны я должен скомпрометировать свой дизайн, у меня гораздо лучше, он достаточно гибкий, чтобы не загрязняют мои классы шаблоном кода и его собственные кишки. – kan

Смежные вопросы