Autowire setter override with Java Config

懵懂的女人 提交于 2019-12-01 10:29:46

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

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

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;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!