我正在尝试实现一个事务性的Web服务端点,因为我不想使用事务方法创建一个特殊的“worker”类。我正在使用Spring-ws库和Spring框架。
这是我的班级定义:
@Endpoint @Transactional @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) public class MyEndpoint implements ApplicationContextAware { ... }
请注意,我明确指定了使用CGLIB强制使用代理方法。
另请注意,我的类实现了一些接口,因此默认情况下,Spring使用JDK动态代理,除非指定了另一个代理方法。在我的情况下,这种代理是不合适的。
当PayloadRootAnnotationMethodEndpointMapping
类开始工作时,问题将从应用程序部署开始。它使用@Endpoint
注释收集所有Spring bean的名称。我的端点类计数两次,名称为“myEndpoint
”和“scopedTarget.myEndpoint
”。这种重复导致ApplicationContextException
消息“无法在注册密钥[...]上映射端点[...]:已经有[...]映射的端点”。
问题:如何使我的端点类成为事务性的?
答案 0 :(得分: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
。