Spring MVC,使用基于类的代理的作用域控制器:“已经有 scopedTarget bean 方法." [英] Spring MVC, Scoped Controller using Class-Based Proxy: 'There is already scopedTarget bean method.'

查看:88
本文介绍了Spring MVC,使用基于类的代理的作用域控制器:“已经有 scopedTarget bean 方法."的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a visual editor Web app using Spring MVC.

可视化有一些属性:

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

每个浏览器会话都应该有一个,所以我将它定义为会话范围的 bean:

Every browser session should have one, so I define it as a session-scoped bean:

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

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

Since I want to access it from the service...

@Service
public class VisualizationService {

    @Resource
    private VisualizationProperties properties;

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

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

...I define access through a proxy:

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

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

make the members private and add getters + setters to it.

到目前为止完美.

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

Now I want the client to be able to read and update the properties.

因此我将 bean 更改为控制器并添加访问自身的方法:

So I change the bean to become a controller and add methods to access itself:

@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;
    }

}

导致启动时出现以下异常:

Causes the following exception on start-up:

IllegalStateException:找到不明确的映射.

无法将 'visualizationProperties' bean 方法 getProperties() 映射到 {[/properties],methods=[GET],...}:

已经有 'scopedTarget.visualizationProperties' bean 方法.

这是为什么?

推荐答案

这里的问题有两个方面.首先,您要注释一个已经用 @Controller 注释的类.

The issue here is two-fold. First you're annotating a class that is already annotated with @Controller.

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

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

Second, you are using scoped proxies. In this case, Spring will register two bean definitions. One with the name visualizationProperties for the actual bean and one with the name scopedTarget.visualizationProperties which will act as a FactoryBean for creating proxies.

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

The handler method registration process (for @Controller beans and @RequestMapping methods) works by finding all bean names in the context, finding their type, scanning the methods of that type and registering those methods if they are annotated with @RequestMapping.

由于 Spring 将 visualizationPropertiesscopedTarget.visualizationProperties bean 名称解析为 VisualizationProperties 类型的 bean,该 bean 具有 @RequestMapping 带注释的方法,它会尝试注册两个,但由于映射冲突而在第二个失败(您不能将两个处理程序映射到同一个请求).

Since Spring resolves both visualizationProperties and scopedTarget.visualizationProperties bean names as beans of type VisualizationProperties which has @RequestMapping annotated methods, it will try to register both, failing on the second because of mapping clashes (you can't have two handler mapped to the same request).

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

My suggested solution is to refactor and create a dedicated @Controller class (that isn't proxied) that delegates to a session scoped VisualizationProperties bean.

这篇关于Spring MVC,使用基于类的代理的作用域控制器:“已经有 scopedTarget bean 方法."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆