Description
Antonio Anzivino opened SPR-15858 and commented
Hi,
I have an optional dependency to listener beans in one of my beans. That means that I could have any number of listeners in my Application context.
I have tried to annotate my bean the following way:
@Autowired(required = false)
@Lazy
private List<Listener> listeners = new ArrayList<>(0);
IMO it is intuitive that Spring will
- Search for Listener beans only when accessed
- Do not crash if no Listener bean is defined in the context, namely return an empty list
I don't know if this is a bug in 4.3.5 or is it just how Spring is designed, but the above code, when no Listener bean is defined, crashes instead of returning an empty list when I try to access the listeners object.
If I use eager initialization, Autowired's required=false injects an empty list. I expected similar behaviour for lazy lists.
This ticket is:
- MINOR because I can workaround this issue by using eager initialization, for the mometn
- IMPROVEMENT because I have found no documentation on whether it is a design choice or an implementation issue
My container bean's afterPropertiesSet does
log.info("I have {} listeners attached", listeners.size());
Instead of logging 0, the application crashes with the following stack trace
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.List<Manager$Listener>' available: Optional dependency not present for lazy injection point
at org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver$1.getTarget(ContextAnnotationAutowireCandidateResolver.java:85)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192)
at com.sun.proxy.$Proxy172.size(Unknown Source)
at com.acme.ManagerImpl.afterPropertiesSet(ManagerImpl.java:75)
Before submitting a test case, I'd first like to be clarified what is the expected Spring's behaviour in such situation
I have reviewed Spring docs on Lazy. The javadoc does not cite the case of optional Collection-dependencies
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Lazy.html
In addition to its role for component initialization, this annotation may also be placed on injection points marked with Autowired or Inject: In that context, it leads to the creation of a lazy-resolution proxy for all affected dependencies, as an alternative to using ObjectFactory or Provider.
Affects: 4.3.5
Issue Links:
- Autowire contract is not honored in cases where FactoryBean or @Bean return null [SPR-15829] #20384 Autowire contract is not honored in cases where FactoryBean or
@Bean
return null