100

有人能解释一下spring@ScopedProxy注解的用法吗?我认为这与会话范围的 bean 有关,但我不太确定是什么。

在我使用范围时,我使用了没有@ScopedProxy注释(或没有 aop 范围代理)的会话范围 bean,所以我非常确定如何正确使用它。

4

2 回答 2

252

spring 文档的第 3.4.4.5 节很好地解释了它:

(请注意,下面的“userPreferences”bean 定义是不完整的):

<!-- an HTTP Session-scoped bean -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

<!-- a singleton-scoped bean -->
<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

从上面的配置中可以明显看出,单例 bean 'userManager' 被注入了对 HTTP 会话范围 bean 'userPreferences' 的引用。这里的重点是'userManager' bean 是一个单例......每个容器将只实例化一次,并且它的依赖项(在这种情况下只有一个,'userPreferences' bean)也只会被注入(一次! ) .

这意味着“userManager”将(概念上)只对完全相同的“userPreferences”对象进行操作,即最初注入的对象。

当您将 HTTP 会话范围的 bean 作为依赖项注入协作对象(通常)时,这不是您想要的。相反,我们想要的是每个容器有一个单独的 'userManager' 对象,然后,在 HTTP Session 的生命周期内,我们希望查看和使用特定于所述 HTTP Session 的 'userPreferences' 对象

相反,您需要的是注入某种对象,该对象公开与 UserPreferences 类完全相同的公共接口(理想情况下是一个 UserPreferences 实例的对象),并且足够聪明,能够启动并获取真正的 UserPreferences 对象来自我们选择的任何底层范围机制(HTTP 请求、会话等)。然后我们可以安全地将这个代理对象注入到 'userManager' bean 中,这将很高兴地不知道它所持有的 UserPreferences 引用是一个代理

在我们的例子中,当一个 UserManager 实例调用依赖注入的 UserPreferences 对象上的一个方法时,它实际上是在调用代理上的一个方法......然后代理将关闭并从中获取真正的 UserPreferences 对象(在这种情况下) HTTP Session,并将方法调用委托给检索到的真实 UserPreferences 对象。

这就是为什么在将请求范围、会话范围和全局会话范围的 bean 注入协作对象时需要以下正确且完整的配置:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
    <aop:scoped-proxy/>
</bean>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>
于 2013-01-17T04:18:28.000 回答
0

在尝试了此处指定的各种不同选项和 spring 文档之后,由于某种原因,我发现 Spring MVC 在您使用 @Controller 注释并且您的 web 应用程序中有多个这样的控制器时会奇怪地自动装配控制器。将注解修改为@RestController (value="UniqueControllerv1"),问题解决。

于 2018-08-10T20:39:23.177 回答