Why @EnableWs removed aop proxy from spring bean

后端 未结 2 1046
旧巷少年郎
旧巷少年郎 2021-01-15 17:58

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         


        
2条回答
  •  春和景丽
    2021-01-15 18:24

    Here's another possibility to solve this issue. This relates to following Stack overflow question: Spring WS interceptors with injected DAO's @Transactional not working. In short the issue comes from the fact that the method

    @Override
    public void addInterceptors(List interceptors) {
    

    gets called before Spring dependency injection has time to register Spring AOP beans. In my case it was @Transactional that was ignored by Spring-WS but it could be anything.

    Fortunately for us Spring-WS uses mutable collections instead of immutable. When the addInterceptors() method gets called, we can just save the collection and thus we have a reference to the same collection instance that is used by Spring-WS. Later on you can initialize your interceptor bean properly and add it to the collection.

    You also have to get around the fact that if you use @Autowired the bean gets prepared before the annotations can take place. Thus you have to create it manually by calling ApplicationContext.getBean() method.

    @EnableWs
    @Configuration
    // The magic is to implement both ApplicationContextAware 
    // that injects the applicationContext for us 
    // and BeanPostProcessor that gives us postProcessBeforeInitialization() 
    // where we initialize our interceptor correctly 
    // and add it to the collection
    public class WebServiceConfig extends WsConfigurerAdapter implements ApplicationContextAware, BeanPostProcessor {
    
        // This is the interceptor that uses dependencies with @Transactional annotation.
        // It will not work with @Autowired
        private MyInterceptorThatHasTransactionalDependencies myInterceptorThatHasTransactionalDependencies;
        // Fortunately Spring WS uses mutable collections so we can fill 
        // this list later on as long as we just initialize it with  
        private List interceptors;
        // This is our application context where all the beans are defined
        private ApplicationContext context;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            // save application context for later use
            this.context = applicationContext;
        }
    
        @Nullable
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            // This method gets called multiple times so initialize interceptor just once
            if(myInterceptorThatHasTransactionalDependencies == null){
                myInterceptorThatHasTransactionalDependencies = context.getBean(MyInterceptorThatHasTransactionalDependencies.class);
                interceptors.add(myInterceptorThatHasTransactionalDependencies);
            }
            return bean;
        }
    
        @Override
        public void addInterceptors(List interceptors) {
            // Save the list of interceptors so we can modify it later on
            this.interceptors = interceptors; 
            if (myInterceptorThatHasTransactionalDependencies == null) {
                System.out.println("myInterceptorThatHasTransactionalDependencies was null like we expected");
            } else {
                interceptors.add(myInterceptorThatHasTransactionalDependencies);
            }
        }
    }
    

    Just to let you know that I am not Spring bean lifecycle expert, so there might be a better place to situate the interceptor initialization than postProcessBeforeInitialization(). That said, this works for me.

提交回复
热议问题