Spring MVC,使用基于类的代理的作用域控制器:“已经有 scopedTarget bean 方法." [英] Spring MVC, Scoped Controller using Class-Based Proxy: 'There is already scopedTarget bean method.'
问题描述
我正在使用 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 将 visualizationProperties
和 scopedTarget.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屋!