Spring fails to autowire fields correctly, if the field contains a generic type variable, which is later bound. It does not matter if the type variable is bound by deriving a concrete (not generic) type or just defining a bean of the generic type with fixed type parameters.
Spring either finds not all beans or too many beans, whereas the second case is especially troublesome as it breaks static type checking.
Consider two beans of types Foo and Bar both implementing an interface Base. Moreover, we have a type BeanCollector<C> which autowires a single field of type List<C>, a field of type C and prints both values after construction. Additionally, a BaseBeanCollector<C behaves the same way, but the type variable has a type bound on Base.We define the following beans:
Here, Foo(Base)BeanCollector are classes which extend (Base)BeanCollector<Foo>.
The really remarkable output of this code is:
Beans for foo base: [com.example.Bar@7fb4f2a9, com.example.Foo@4dc27487]
Beans for foo:  and org.springframework.jmx.export.annotation.AnnotationMBeanExporter@13df2a8c
Beans for bar base: [com.example.Bar@7fb4f2a9, com.example.Foo@4dc27487]
Beans for foo base anonymous class: [com.example.Foo@4dc27487]
Beans for bar base anonymous class: [com.example.Bar@7fb4f2a9]
Beans for foo anonymous class:  and com.example.Foo@4dc27487
Beans for bar anonymous class:  and com.example.Bar@7fb4f2a9
Beans for foo extra class:  and com.example.Foo@4dc27487
Beans for foo base extra class: [com.example.Foo@4dc27487]
Beans for bar:  and org.springframework.jmx.export.annotation.AnnotationMBeanExporter@13df2a8c
The following table shows the autowiring behaviour:
| | collector instance without extra Type | collector instance as anonymous type | collector instance as class type |
| no type bound | empty bean list, arbitrary single bean | empty bean list | empty bean list |
| type bound | too many beans in list | OK | OK |
Either, spring should behave as expected, or report an error that autowiring using type variables is not supported. The current behaviour can trigger all kind of subtle bugs.
As a consequence, the bean class itself needs to contain the variable substitution. According to Java type erasure, this is the case for extends and implements clauses in a type hierarchy, with anonymous inner classes as a special case thereof. Plain instantiation with construction-time substitution of the variable does not retain the type variable: the effect of type erasure as originally designed in Java.
Lastly, collection autowiring in fields does not take the containing class into account, in contrast to collection autowiring in method parameters where this has been working for a long time already. This is why you are seeing empty bean lists even for your class hierarchy substitution cases.
While the former two constraints are currently by design, the latter is an unintended inconsistency. I'll turn this JIRA ticket into a bug fix there, closing the gap between field and method parameter scenarios. For the factory method return type consideration, let's keep tracking this in #16146.
Note that I cannot reproduce an arbitrary bean getting selected. For unresolvable type variables, I always see the base type - or Object in case of no type constraints - getting picked up, leading to a corresponding exception if the result is not unique. This is the case against 5.0 at least; I'll double-check against 4.3.6 which I'm going to backport this fix to.