java - 为什么@EnableWs 从 spring bean 中删除了 aop 代理
问题描述
我正在尝试在我的 Spring Boot Web 服务项目中添加自定义拦截器。我按照这个例子创建了这个配置:
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上。
解决方案
问题是 Spring 中的初始化序列。从技术上讲,因为有一个BeanPostProcessor
用于 WS 端点(AnnotationActionEndpointMapping
在 spring-ws 中),它将强制提前初始化所需的任何依赖项——尤其是任何EndpointInterceptor
bean。
解决此问题的一种方法是重新排列 BeanPostProcessor,甚至创建自己的,但通常在 Spring 中保持默认配置更简单 - 以避免在初始化序列的其他地方出现类似的意外。
避免该问题的更简单方法可能是ObjectFactory
在EndpointInterceptor
bean 中使用 an 。这将延迟实例化AppConfig
bean,直到它被引用,此时 Aop 编织也将发生。
@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 中引用它。
感谢您的示例 - 这里有一个使用该ObjectFactory
技术的叉子。当我从 SoapUI 发送请求时,这将 bean 显示为所有的config
Aop 代理。WsConfig.testAop()
CountryEndpoint
CustomValidatingInterceptor
推荐阅读
- javascript - JSON 错误中出现意外的令牌,但我使用的是“produces = “text/plain””?
- python - Django,根据来自另一个模型的值创建自定义订单/过滤器
- codeigniter - 如何在 CodeIgniter 3 中下载生成的 PDF?
- nginx - 我如何从基本 url 重写/重定向以在 NGINX 中指定 localhost url?
- clickhouse - clickhouse 设置中的 max_concurrent_queries_for_all_user 和 max_concurrent_queries 有什么区别?
- excel - Excel中单元格值的点运算
- html - 定位和响应问题
- php - 根据 laravel 中复选框的选择计算总值
- java - 如果将 HashMap 转换为数组,为什么将数组初始化为 >0 将不起作用
- css - 使用引导程序 5 为列创建不同的高度