java - 为什么@EnableWs从spring bean中删除aop代理

标签 java spring spring-boot aop

我正在尝试在我的 Spring Boot Web 服务项目中添加自定义拦截器。我关注this示例并创建了此配置:

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的初始化顺序上。从技术上讲,因为 WS 端点有一个 BeanPostProcessor(spring-ws 中的 AnnotationActionEndpointMapping),它将强制提前初始化所需的任何依赖项 - 尤其是任何 EndpointInterceptor bean。

解决这个问题的一种方法是重新排列 BeanPostProcessor,甚至创建您自己的 BeanPostProcessor,但通常更简单的是保留 Spring 中的默认配置 - 以避免初始化序列中其他地方出现类似的意外情况。

也许避免该问题的更简单方法是在 EndpointInterceptor bean 中使用 ObjectFactory。这将延迟实例化 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 引用为注入(inject)( Autowiring )bean。

感谢您提供的示例 - 有一个 fork here使用 ObjectFactory 技术。这显示了 config bean 作为所有 WsConfig.testAop()CountryEndpointCustomValidatingInterceptor 中的 Aop 代理> 当我从 SoapUI 发送请求时。

关于java - 为什么@EnableWs从spring bean中删除aop代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50072312/

相关文章:

java - 如何组织辅助函数

java - createNativeQuery 中的分页

java - 如何修复外部 jar 导入中的 Autowiring

java - 正则表达式 "Or"返回一组Java

java - 左右展开java二维数组

java - RestTemplate 不传递 Origin header

java - 在不同的 Spring 上下文中加载属性

java - Spring 方面记录器

spring-boot - 如何在 Spring Boot 中禁用 jndi 调试日志

spring-boot - Springfox Java Bean 验证未显示在 Swagger 输出中