Disabling AutoCode Using Java Config

Consider the following class:

public class MyBean { private A a; @Autowired(required=true) public void setA(A a) { this.a = a; } public A getA() { return a; } } 

There are times when it is necessary to redefine automatic injection, for example, when Spring cannot find one candidate for injection. In XML, I can give the following example:

 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="first" class="my.pkg.AImpl"/> <bean id="second" class="my.pkg.AImpl"/> <bean id="myBeanFirst" class="my.pkg.MyBean"> <property name="a" ref="first"/> </bean> <bean id="myBeanSecond" class="my.pkg.MyBean"> <property name="a" ref="second"/> </bean> </beans> 

Is there a way to do the same with Java Config? The following does not work (and I understand why), because Spring tries to autwire the property after returning from the myBean method, and it does not work with NoUniqueBeanDefinitionException:

 @Configuration public class MyConfig { @Bean public A first() { return new AImpl(); } @Bean public A second() { return new AImpl(); } @Bean public MyBean myBeanFirst(A first) { MyBean myBean = new MyBean(); myBean.setA(first); return myBean; } @Bean public MyBean myBeanSecond(A second) { MyBean myBean = new MyBean(); myBean.setA(first); return myBean; } } 

To change the MyBean class is not always an option, for example, because it comes from an external library. Is this the case when I need to use XML configuration?

Thanks Andrea Polci

Update Thanks for the two solutions, so the tariff (injection by name and using @Primary), but they do not solve my use case, so I have to be more specific, I think.

In my case, the use of the MyBean class comes from an external library, so any change is not possible. I also need to have more than one instance of MyBean, each of which introduces different capabilities of interface A. I updated the code above to reflect this (both xml and java).

Is there any solution using java config? Can I Avoid Autocovering MyBean Dependence? (Only on beans of this class, and not completely disable auto-connect for each bean in context)

+2
java spring spring-java-config
source share
3 answers

Well, here it is, I believe that this answer will satisfy your needs.

We need an implementation of MergedBeanDefinitionPostProcessor that sets the correct value for the a property of the MyBean class. This can be done in 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 are hardcoded here, but they can be set in a static final string, which will also be used by @Bean annotations in the following code

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

In the following code, you will notice that setA is not called in the methods of creating MyBean, because no matter what value we set (or in this case we do not set), it will be overridden when Spring runs the mail processor bean.

If you want the default value for A (if, for example, you paste it into another beans), go to the @Bean definition in the previous configuration

+3
source share

If you have multiple candidates for injection, you can specify a default value using @Primary on the bean that you want to use AImpl by default. Thus, no changes to MyBean are required

+2
source share

If you want to use myBeanFirst first, just call first() . Same thing for myBeanSecond, want it to use the second one, and 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
source share

All Articles