为什么@EnableWs 从 spring bean 中删除了 aop 代理 [英] Why @EnableWs removed aop proxy from spring bean
问题描述
我正在尝试在我的 Spring Boot Web 服务项目中添加自定义拦截器.我按照 this 示例创建了这个配置:>
I am trying to add custom interceptor in my spring boot web service project. I follow this example and created this config:
package org.example;
import java.util.List;
import org.aspect.PersistentAspect;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
@EnableWs
@Configuration
public class WsConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
final MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/v1/*");
}
@Bean
public XsdSchema schema() {
return new SimpleXsdSchema(new ClassPathResource("country.xsd"));
}
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
String[] jaxbContext = new String[] { "io.spring.guides.gs_producing_web_service" };
marshaller.setContextPaths(jaxbContext);
return marshaller;
}
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
// aop not working
interceptors.add(new CustomValidatingInterceptor(schema(), config()));
// aop working
// interceptors.add(new CustomValidatingInterceptor(schema(), null));
}
@Bean
public AppConfig config() {
return new AppConfig();
}
@Bean
public PersistentAspect persistentAspect() {
PersistentAspect persistentAspect = new PersistentAspect();
return persistentAspect;
}
@Bean
public Object testAop() {
System.out.println("is config aop proxy: " + AopUtils.isAopProxy(config()));
return null;
}
}
但是,当我在 addInterceptors
方法中添加新的拦截器时,我在配置类中删除了 aop 代理时遇到了问题.知道为什么吗?整个项目都在 git 上.
however when I am adding new interceptor in addInterceptors
method I have problem with removed aop proxy in my config class. Any idea why ? Whole project is on git.
推荐答案
问题是 Spring 中的初始化顺序.从技术上讲,因为 WS 端点有一个 BeanPostProcessor
(spring-ws 中的 AnnotationActionEndpointMapping
),它将强制提前初始化任何需要的依赖项 - 特别是任何 EndpointInterceptor
bean.
The problem is the initialization sequence in Spring. Technically, because there is a BeanPostProcessor
for the WS Endpoint (AnnotationActionEndpointMapping
in spring-ws), it will force the early initialization of any dependencies this needs - especially any EndpointInterceptor
beans.
解决这个问题的一种方法是重新排列 BeanPostProcessor 的,甚至创建自己的一个,但通常保持 Spring 中的默认配置更简单 - 以避免在初始化序列的其他地方出现类似的意外.
One way to counter this is to rearrange the BeanPostProcessor's, or even create one of your own, but usually its simpler to stay with the default configuration in Spring - to avoid similar surprises elsewhere in the initialization sequence.
也许避免该问题的更简单方法是在 EndpointInterceptor
bean 中使用 ObjectFactory
.这将延迟 AppConfig
bean 的实例化,直到它被引用,此时 Aop 编织也将发生.
Perhaps a simpler way to avoid the problem is to use an ObjectFactory
in the EndpointInterceptor
bean. This will delay instantiating the AppConfig
bean until it is referenced, by which time the Aop weaving will also have taken place.
@Component
public class CustomValidatingInterceptor extends PayloadValidatingInterceptor {
@Autowired
private ObjectFactory<AppConfig> konfigurace;
@Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws IOException, SAXException, TransformerException {
System.out.println("is config aop proxy in interceptor: " +
AopUtils.isAopProxy(konfigurace.getObject()));
return super.handleRequest(messageContext, endpoint);
}
显然,这意味着 CustomValidatingInterceptor
必须从 WsConfig
引用为注入(自动装配)bean.
Clearly, this then means the CustomValidatingInterceptor
must be referenced from WsConfig
as an injected (autowired) bean.
感谢您提供的示例 - 此处 使用了 ObjectFactory
技术.这将 config
bean 显示为所有 WsConfig.testAop()
、CountryEndpoint
和 CustomValidatingInterceptor
中的 Aop 代理> 当我从 SoapUI 发送请求时.
Thanks for the example - there's a fork here that uses the ObjectFactory
technique. This showed the config
bean as an Aop proxy in all of WsConfig.testAop()
, the CountryEndpoint
and the CustomValidatingInterceptor
when I sent a request in from SoapUI.
这篇关于为什么@EnableWs 从 spring bean 中删除了 aop 代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!