Spring MVC,Scoped Controller使用基于类的代理:'已经有scopedTarget bean方法'。

时间:2013-12-06 23:31:40

标签: java session spring-mvc spring-annotations

我正在使用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 {
    ...

将成员设为私有,并为其添加getters + 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.

为什么?

2 个答案:

答案 0 :(得分:3)

这里的问题是双重的。首先,您要注释已使用@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名称解析为具有VisualizationProperties注释方法的类型@RequestMapping的bean,它将尝试注册两者,在第二个时失败因为映射冲突(你不能将两个处理程序映射到同一个请求)。

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

答案 1 :(得分:0)

有效的替代方案:

  • 将访问方法移动到另一个控制器.. 封装meh!
  • 使用proxyMode=ScopedProxyMode.INTERFACES,将可爱的小属性POJO移至VisualizationProperties Impl 并为其引入界面.. overhead duh!< / em>的

其他想法?