2

我正在尝试实现一个具有事务性的 Web 服务端点,因为我不想使用事务性方法创建一个特殊的“工作者”类。我将 Spring-ws 库与 Spring 框架一起使用。

这是我的类定义:

@端点
@Transactional
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
公共类 MyEndpoint 实现 ApplicationContextAware { ... }

请注意,我明确指定了强制使用 CGLIB 的代理方法。

另请注意,我的类实现了一些接口,因此默认情况下 Spring 使用 JDK 动态代理,除非指定了另一个代理方法。这种代理不适合我的情况。

PayloadRootAnnotationMethodEndpointMapping类开始工作时,问题开始于应用程序部署。它收集所有带有@Endpoint注释的 Spring bean 的名称。我的端点类用名称“ myEndpoint”和“ scopedTarget.myEndpoint”计算两次。这种重复导致ApplicationContextException消息“无法在注册密钥 [...] 上映射端点 [...]:已经映射了端点 [...]”。

问题:如何使我的端点类具有事务性?

4

1 回答 1

0

您可以编写自己的PayloadRootAnnotationMethodEndpointMapping扩展并覆盖该initApplicationContext方法。在那里,您可以检查scopedTarget.前缀以过滤掉不需要的 bean:

public class ProxiedBeanAwareEndpointMapping extends PayloadRootAnnotationMethodEndpointMapping {

    @Override
    protected void initApplicationContext() throws BeansException {
        initInterceptors();
        String[] beanNames = getApplicationContext().getBeanNamesForType(Object.class);
        for (String beanName : beanNames) {
            if (!beanName.startsWith("scopedTarget.")) {
                Class<?> endpointClass = getApplicationContext().getType(beanName);
                if (endpointClass != null && AnnotationUtils.findAnnotation(endpointClass, getEndpointAnnotationType()) != null) {
                    registerMethods(beanName);
                }
            }
        }
    }

}

或者您可以使用open session in view方法,这样您就不需要代理您@Endpoint的 s.

于 2013-05-30T23:14:04.557 回答