使用Spring-ws库在同一个类上使用@Endpoint和@Transactional



我试图实现一个web服务端点,这将是事务性的,因为我不想用事务性方法创建一个特殊的"工作者"类。我正在使用Spring-ws库和Spring框架。

下面是我的类定义: <>之前@Endpoint@ transactional@Scope (proxyMode = ScopedProxyMode.TARGET_CLASS)公共类MyEndpoint实现ApplicationContextAware{…}之前

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

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

PayloadRootAnnotationMethodEndpointMapping类开始工作时,问题开始于应用程序部署。它收集所有带有@Endpoint注释的Spring bean的名称。我的端点类计数两次,名称为"myEndpoint"one_answers"scopedTarget.myEndpoint"。此复制导致ApplicationContextException显示消息"无法映射端点[…]注册键[…]:已经有终点了[…]映射"。

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

您可以编写自己的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

最新更新