【问题标题】:Spring MVC, Scoped Controller using Class-Based Proxy: 'There is already scopedTarget bean method.'Spring MVC,使用基于类的代理的作用域控制器:“已经有作用域目标 bean 方法。”
【发布时间】:2013-12-07 08:15:33
【问题描述】:

我正在使用 Spring MVC 创建一个可视化编辑器 Web 应用程序。

可视化具有一些属性:

public class VisualizationProperties {
    double strokeWidth = 1;
    Rectangle selectedArea;
}

每个浏览器会话都应该有一个,因此我将其定义为会话范围的 bean:

@Component
@Scope("session")
public class VisualizationProperties {
    ...

因为我想从服务中访问它...

@Service
public class VisualizationService {

    @Resource
    private VisualizationProperties properties;

    public void createVisualization () {
        //create visualization using properties
        ...
    }
}

...我通过代理定义访问:

@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {
    ...

将成员设为私有并为其添加 getter + setter。

到目前为止完美。

现在我希望客户端能够读取和更新属性。

所以我把bean改成控制器并添加方法来访问自己:

@Controller
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {

    private double strokeWidth = 1;
    private Rectangle selectedArea;

    ... //getters + setters

    @RequestMapping(value="/properties", method=RequestMethod.GET)
    public @ResponseBody VisualizationProperties getProperties () {
        return this;
    }

    @RequestMapping(value="/properties", method=RequestMethod.POST)
    public @ResponseBody void setProperties (@RequestBody VisualizationProperties newProperties) {
        this.strokeWidth  = newProperties.strokeWidth;
        this.selectedArea = newProperties.selectedArea;
    }

}

在启动时导致以下异常:

IllegalStateException: Ambiguous mapping found.

Cannot map 'visualizationProperties' bean method getProperties() to {[/properties],methods=[GET],...}:

There is already 'scopedTarget.visualizationProperties' bean method.

这是为什么呢?

【问题讨论】:

  • 可行的替代方案:将访问方法移动到不同的控制器(放弃封装)或使用 proxyMode=ScopedProxyMode.INTERFACES 并将属性 POJO 移动到 VisualizationPropertiesImpl 并引入它的接口(不需要的开销)。其他想法?

标签: java session spring-mvc spring-annotations


【解决方案1】:

这里的问题是双重的。首先,您要注释一个已经用 @Controller 注释的类。

@Controller
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class VisualizationProperties {

其次,您正在使用范围代理。在这种情况下,Spring 将注册两个 bean 定义。一个名称为 visualizationProperties 的实际 bean 和一个名称为 scopedTarget.visualizationProperties 的名称将充当 FactoryBean 用于创建代理。

处理程序方法注册过程(对于@Controller bean 和@RequestMapping 方法)通过在上下文中查找所有bean 名称、找到它们的类型、扫描该类型的方法并注册这些方法来工作方法,如果它们用 @RequestMapping 注释。

由于 Spring 将 visualizationPropertiesscopedTarget.visualizationProperties bean 名称解析为具有 @RequestMapping 注释方法的 VisualizationProperties 类型的 bean,因此它将尝试注册两者,由于映射冲突而在第二个失败(你可以' t 有两个处理程序映射到同一个请求)。

我建议的解决方案是重构并创建一个专用的 @Controller 类(未代理),该类委托给范围为 VisualizationProperties bean 的会话。

【讨论】:

  • 请详细说明委托人模式?委托类范围和代理模式是什么?服务和/或组件将如何注入到委托类中?
  • @Sam 我建议不要在@Controller 中执行会话范围的事情,而是将该行为放在一个单独的 bean 中,该 bean 本身就是会话范围的。注入将正常进行。
  • 您还可以使用@Primary 注释工厂bean,以使规范bean 具有优先权。
猜你喜欢
  • 2020-10-06
  • 2012-12-31
  • 1970-01-01
  • 2015-06-10
  • 2011-03-13
  • 1970-01-01
  • 2017-06-27
  • 2017-09-02
  • 2014-10-11
相关资源
最近更新 更多