Spring MVC,使用基于类的代理的作用域控制器:“已经有scopedTarget bean方法。”
问题内容:
我正在使用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 + setters。
到目前为止完美。
现在,我希望客户端能够读取和更新属性。
因此,我将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.
这是为什么?
问题答案:
这里的问题有两个方面。首先,您要注释一个已经用注释过的类@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将bean名称visualizationProperties
和scopedTarget.visualizationProperties
bean名称都解析为VisualizationProperties
具有@RequestMapping
注释方法的bean类型,因此它将尝试同时注册两者,由于映射冲突(第二个处理程序不能映射到同一请求)而导致第二次失败。
我建议的解决方案是重构并创建一个专用@Controller
类(未代理),该类委派给会话范围的VisualizationProperties
bean。