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

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

问题描述

我正在尝试在我的Spring Boot Web服务项目中添加自定义拦截器.我遵循示例,并创建了以下配置:

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,甚至创建自己的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技术.当我从SoapUI发送请求时,这显示config bean作为所有WsConfig.testAop()CountryEndpointCustomValidatingInterceptor中的Aop代理.

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天全站免登陆