简体   繁体   English

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

[英]Spring MVC, Scoped Controller using Class-Based Proxy: 'There is already scopedTarget bean method.'

I'm creating a visual editor Web app using Spring MVC. 我正在使用Spring MVC创建一个可视化编辑器Web应用程序。

The visualizaton has some properties: visualizaton有一些属性:

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

Every browser session should have one, so I define it as a session-scoped bean: 每个浏览器会话应该有一个,所以我将其定义为会话范围的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 {
    ...

make the members private and add getters + setters to it. 使成员私有,并添加getters + setter。

Perfect so far. 到目前为止完美。

Now I want the client to be able to read and update the properties. 现在我希望客户端能够读取和更新属性。

So I change the bean to become a controller and add methods to access itself: 所以我将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;
    }

}

Causes the following exception on start-up: 在启动时导致以下异常:

IllegalStateException: Ambiguous mapping found.

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

There is already 'scopedTarget.visualizationProperties' bean method.

Why is that? 这是为什么?

The issue here is two-fold. 这里的问题是双重的。 First you're annotating a class that is already annotated with @Controller . 首先,您要注释一个已经使用@Controller注释的类。

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

Second, you are using scoped proxies. 其次,您正在使用范围代理。 In this case, Spring will register two bean definitions. 在这种情况下,Spring将注册两个bean定义。 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. 一个名为visualizationProperties用于实际bean,另一个名为scopedTarget.visualizationProperties ,用作创建代理的FactoryBean

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 . 处理程序方法注册过程(对于@Controller bean和@RequestMapping方法)通过查找上下文中的所有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). 由于Spring解决了这两个visualizationPropertiesscopedTarget.visualizationProperties bean名字类型的豆VisualizationProperties@RequestMapping注解的方法,它会尝试注册这两个,没有按规定因为映射冲突的第二个(你不能有两个处理程序映射到相同请求)。

My suggested solution is to refactor and create a dedicated @Controller class (that isn't proxied) that delegates to a session scoped VisualizationProperties bean. 我建议的解决方案是重构并创建一个委托给会话范围的VisualizationProperties bean的专用@Controller类(不代理)。

Alternatives that work: 有效的替代方案:

  • Moving the access methods to a different controller .. encapsulation meh! 将访问方法移动到不同的控制器.. 封装meh!
  • Using proxyMode=ScopedProxyMode.INTERFACES , move the cute little properties POJO to a VisualizationProperties Impl and introduce an interface for it .. overhead duh! 使用proxyMode=ScopedProxyMode.INTERFACES ,将可爱的小属性POJO移动到VisualizationProperties Impl并为它引入一个接口.. proxyMode=ScopedProxyMode.INTERFACES

other ideas? 其他想法?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring 3 MVC:在MVC Controller方法参数中公开会话范围的bean - Spring 3 MVC: Expose session scoped bean in MVC Controller method arguments 会话范围 bean 作为 Spring MVC 控制器的类属性 - Session scoped bean as class attribute of Spring MVC Controller spring 作用域代理 bean - spring scoped proxy bean Bean 'scopedTarget.oauth2ClientContext' 无法注册相同的 bean 名称已在类路径中定义 - Bean 'scopedTarget.oauth2ClientContext' could not be registered same bean name has already been defined in class path 自动绑定/将作用域bean注入控制器方法 - Autowire/inject scoped bean into controller method Spring MVC范围内的Bean依赖关系和竞争条件 - Spring MVC Scoped Bean Dependencies and Race Conditions 使用AOP作用域代理在单例bean中自动装配原型bean - Using AOP scoped proxy to autowire prototype bean in a singleton bean Spring mvc控制器bean配置 - Spring mvc controller bean configuration Spring应该使用AOP代理bean调用每个方法 - Spring Every method should called using AOP proxy bean 在Spring MVC中,使用会话范围的bean完成操作后,是否需要解除绑定到该会话的bean对象的绑定? 如果是,怎么办? - In Spring MVC, do I need to unbind bean objects bound to the session when I am done using the session scoped bean? If yes, how?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM