Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Honor @Autowired(required=false) at parameter level, as an alternative to java.util.Optional [SPR-15268] #19833

Closed
spring-projects-issues opened this issue Feb 19, 2017 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 19, 2017

Rafael Winterhalter opened SPR-15268 and commented

When declaring a dependency on a list of beans in a Java config, the @Autowired(required = false) annotation is not respected when no suitable bean exists such as:

@Bean public Bar bar(@Autowired(required = false) List<Foo> foos);

The exception states:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bar' defined in dep.DepConfig: Unsatisfied dependency expressed through method 'bar' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<foo.Foo>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=false)}

Expressing the constraint on a constructor or field does however work. Also, it is possible to declare the parameter as Optional where an empty optional is provided.


Affects: 4.3.6

Issue Links:

Referenced from: commits d74542e, beac891

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 19, 2017

Juergen Hoeller commented

Originally, we only supported @Autowired at the method/constructor/field level but not for individual parameters. As of #18629 (Spring Framework 4.3), we allow it to be used at the parameter level, in particular for use with JUnit 5 test methods... but we don't process it at the parameter level for regular injection points where @Autowired demarcates an configuration-time injection point (i.e. a method/constructor/field), not an individual argument.

We've already considered detecting @Autowired at the parameter level for regular injection points as well, exactly for the purpose that you intuitively used it for: a required=false indication for a particular argument, as an alternative to java.util.Optional. This didn't seem compelling enough at that time, but since your intuition led you to trying it, I'm reconsidering whether to leniently detect it for the 'optional' indication.

That said, such parameter-level detection of @Autowired isn't entirely trivial implementation-wise. With its current role of triggering an injection point, its use is nicely factored out into a post-processor. Since constructor argument resolution (also applied to factory methods) lives in a separate part of the codebase, mingling @Autowired detection in there just for detecting the required flag seems unclean. I'll see what I can do here to keep those concerns separated while still detecting annotation-based optional markers.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 20, 2017

Rafael Winterhalter commented

Thanks for the feedback. With this historic information, it makes sense why it did not work but, as you said, I would have expected the annotation to not apply to parameters. I think allowing for this would make the use more intuitive, especially since nothing is mentioned in the javadoc and as I could not find anything when googling.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented May 3, 2017

Juergen Hoeller commented

We're performing such annotation-based 'required' detection in QualifierAnnotationAutowireCandidateResolver now, hidden behind the AutowireCandidateResolver SPI. This is very straightforward and easy enough to add to the SPI for 5.0. For 4.3.x, we can do a conditional downcast to SimpleAutowireCandidateResolver, avoiding the addition of a new method to the AutowireCandidateResolver interface, so I intend to backport this to 4.3.9 as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants