@Mike, The behavior is actually expected - both the @Component annotated class and @Bean method create a bean definition with the exact same name "foo" and one ends up(here the one annotated with @Component) overriding the other and hence the behavior.
You will see the right behavior if one of the beans has a different name. eg.
I don't think this is the users' expected behavior at all. If i were to do this with explicit @Bean definitions instead of component scanning it would work fine. Because I switch to component scannig... all of a sudden this breaks. This is broken.
Related to #14316
I'm mark this as "Works as Designed" since bean definition overriding has nothing to do with @Primary. If a bean is being overridden by name, any qualification marker such as @Primary won't have the intended effect. The clue is the "by name" part: Differently named @Bean methods or specifically named @Component classes will make it work.
That said, we are about to revise the general overriding rule for component scanned classes versus @Bean methods in #14201, which is essentially the appropriate solution for this scenario as well.