Autowire setter override with Java Config

前端 未结 3 1831
故里飘歌
故里飘歌 2021-01-15 03:27

Consider the following class:

public class MyBean {
    private A a;

    @Autowired(required=true)
    public void setA(A a) {
        this.a = a;
    }

           


        
相关标签:
3条回答
  • 2021-01-15 03:54

    If you have multiple candidates for injection you can specify the default one by using @Primary on the bean you want to be the default AImpl. That way no changes are needed to MyBean

    0 讨论(0)
  • 2021-01-15 03:59

    Ok here it goes, I believe this answer will satisfy your needs.

    What we need is an implementation of MergedBeanDefinitionPostProcessor that will set the correct value for the property a of class MyBean. This can be done by the following class

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
    import org.springframework.beans.factory.support.RootBeanDefinition;
    import org.springframework.stereotype.Component;
    
    
    @Component
    public class MyBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
    
    
        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            if(beanName.equals("myBeanFirst")) {
                beanDefinition.getPropertyValues().add("a", getMyBeanFirstAImpl());
            }
            else if(beanName.equals("myBeanSecond")) {
                beanDefinition.getPropertyValues().add("a", getMyBeanSecondAImpl());
            }
        }
    
        private Object getMyBeanFirstAImpl() {
            return new AImpl();
        }
    
        private Object getMyBeanSecondAImpl() {
            return new AImpl();
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    

    As you can see the names of the beans here are hardcoded but they could be set in static final String that would be also used by the @Bean annotations in the following code

    @Configuration
    public class Configuration {
    
    
    
        @Bean
        public MyBean myBeanFirst() {
            return new MyBean();
        }
    
        @Bean
        public MyBean myBeanSecond() {
            return new MyBean();
        }
    
    }
    

    You will notice in the following code that setA is not called in the MyBean creation methods, because no matter what value we set (or in this case don't set) will be overridden when Spring executes the bean post processor.

    In case you need a default value for A (if for example you are injecting it in other beans), proceed to define a @Bean in the previous configuration

    0 讨论(0)
  • 2021-01-15 04:00

    If you want myBeanFirst to use first, then just call first(). Same for myBeanSecond, want it to use second, then just call second() when setting A;

    @Configuration
    public class MyConfig {
        @Bean
        public A first() {
            return new AImpl();
        }
    
        @Bean
        public A second() {
            return new AImpl();
        }
    
        @Bean
        public MyBean myBeanFirst() {
            MyBean myBean = new MyBean();
            myBean.setA(first());
            return myBean;
        }
    
        @Bean
        public MyBean myBeanSecond() {
            MyBean myBean = new MyBean();
            myBean.setA(second());
            return myBean;
        }
    }
    
    0 讨论(0)
提交回复
热议问题