为什么@EnableWs 从 spring bean 中删除了 aop 代理 [英] Why @EnableWs removed aop proxy from spring bean

查看:29
本文介绍了为什么@EnableWs 从 spring bean 中删除了 aop 代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 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()CountryEndpointCustomValidatingInterceptor 中的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆