【问题标题】:session or request scope variable in SpringSpring中的会话或请求范围变量
【发布时间】:2014-03-06 07:48:27
【问题描述】:

我想在 Spring 中有一个作用域变量。在 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();
    }
}

我如何在 Spring 中做类似的事情?

请记住,它是 java.lang.Integer,而不是某些用户 bean,它不能被 aop 代理。

【问题讨论】:

    标签: java spring web-applications guice


    【解决方案1】:

    在您的情况下,您不需要会话范围。您只需要一个单例自定义提供程序实例

    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.


    一般用于会话范围的 bean:

    @Configuration 类中,您可以提供具有会话范围的@Bean 方法。

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

    您也可以在@Component 注释类上使用@Scope 注释。

    在 XML 中

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

    【讨论】:

    • 又该如何使用呢?你能显示注射点吗?请记住,它是 java.lang.String,而不是 SomeBean,它无法被代理。
    • @kan 啊,我没看到。让我回复你。
    • @kan 我认为这是你能做的最好的。与您在 Guice 中所做的相匹配。
    • 嗯,他确实需要会话范围才能在同一会话中获得相同的值。使用您的提供者添加答案。
    • @EmersonFarrugia 啊,应该已经阅读了代码中的 cmets。
    【解决方案2】:
    @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();
    

    【讨论】:

    • 这是我自己做过的最好的事情,但我不得不在提供者中缓存值...在更复杂的场景中 - 值是从其他注入的 bean 中计算出来的,我无法在构造函数,看起来更糟,我需要添加多线程安全性。
    • 听起来你的领域模型不够强大。问问自己“这些值是什么意思?” “为什么他们的会话范围?” “他们有什么关系?”等等。如果您可以将它们建模为实体对象 (martinfowler.com/bliki/EvansClassification.html),那么您可以使该对象成为具有会话范围的 bean,将其注入您需要的任何位置,并让其他 bean 对其进行变异。
    • 我不喜欢 Spring 如此侵入性,它决定了我应该如何设计域模型。目前它只是一个缓存参数,如果它变得更清楚它应该在域模型中如何,我会对其进行重构,但是由于 spring 我应该使我的设计过于复杂,guice 要好得多,它足够灵活,不会用样板代码和它自己的胆量污染我的课程。
    • 顺便说一句,Provider&lt;Integer&gt; 的方法对我不起作用,spring 自动装配自己的 DefaultListableBeanFactory.DependencyProvider 类,然后在上下文中懒惰地查找 Integer 类型,没有注意到 @ 987654328@,因为据我了解,它不支持泛型。所以,我应该创建CustomIntegerProvider 垃圾类。我已经讨厌春天了。
    • 回复:Provider,我以为那是你自己的课,我的回答只是对@sotirios-delimanolis 的CustomProvider 的跟进。回复:泛型,假设您使用的是 Spring 4,Spring 确实支持使用泛型类型自动装配类。回复:您的域模型,我的意思是考虑您在做什么;您实际上是按名称注入了一个魔术整数。这是一种“全局变量”的代码气味,无论您使用的是 Guice、Spring 还是其他任何东西。 Integer 也是最终对象,防止容器构建代理来桥接会话和单例范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2014-12-02
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多