spring-projects / spring-projects/spring-framework
Should @Configuration mark @Inject fields and setters as satisfied (injected)? [SPR-14180]
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Christian Hersevoort opened SPR-14180 and commented
Somewhat related to my other issue: #18750 (It's a different way to solve the same problem)
The case is as follows:
Beans:
- MyParentBean
- MyChildBeanA implements MyChildBean
- MyChildBeanB implements MyChildBean
@Configuration
public class MyBeanConfiguration
{
@Bean
public MyParentBean myParentBean(MyChildBeanA childBeanA)
{
MyParentBean myParentBean = new MyParentBean();
myParentBean.setMyChild(childBeanA);
return myParentBean;
}
}
@Component
public class MyParentBean
{
private MyChildBean myChild;
@Inject
public void setMyChild(MyChildBean myChild)
{
this.myChild = myChild;
}
}
I expect the MyParentBean.myChild field to only be Injected by the @Configuration, and not by both ConfigurationClassPostProcessor and the AutowiredAnnotationBeanPostProcessor.
Expected:
- ConfigurationClassPostProcessor calls MyBeanConfiguration
- MyParentBean is created and field/property myChild is set.
- myChild is marked as satisfied(Injected)
What happens:
- ConfigurationClassPostProcessor calls MyBeanConfiguration
- MyParentBean is created and field/property myChild is set.
- AutowiredAnnotationBeanPostProcessor tries to Inject myChild again, but fails and throws a NoUniqueBeanDefinitionException
Changing between field and property injection doesn't help either e.g:
@Component
public class MyParentBean
{
@Inject
private MyChildBean myChild;
}
Changing @Bean to @Bean(autowire = Autowire.NO) doesn't help either, e.g:
@Configuration
public class MyBeanConfiguration
{
@Bean(autowire = Autowire.NO)
public MyParentBean myParentBean(MyChildBeanA childBeanA)
{
MyParentBean myParentBean = new MyParentBean();
myParentBean.setMyChild(childBeanA);
return myParentBean;
}
}
Is this expected behavior? I expect org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#checkPropertySkipping to be true and skip injection.
If this is expected behavior: is there a way to prevent @Bean to be injected again by the AutowiredAnnotationBeanPostProcessor?
Issue Links:
- #18750 Inconsistency between property Injection and setter Injection causes NoUniqueBeanDefinitionException
- #18854 Clarify
@Bean(autowire=NO)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing ConfigurationClassPostProcessor and AutowiredAnnotationBeanPostProcessor for the MyParentBean example, then inspect InjectionMetadata.InjectedElement#checkPropertySkipping. Determine whether configuration-time setter or field injection should be recognized as already satisfied, and define completion as preventing the duplicate injection and resulting NoUniqueBeanDefinitionException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100