我试图实现一个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
了