Hello Spring-Team,

thank you for your continued work in maintaining this excellent framework. I've come across what appears to be an inconsistency in how qualifiers work in hierarchical contexts and wanted to bring it to your attention.

When using @Qualifier annotations in a parent-child context hierarchy, qualifier values don't properly override field names, contradicting Spring's documented behaviour. Here is a simplified code sample:

// Parent context beans
@Bean({ "open.right","right"})
public TestInterface right() {
    return () -> false;
}

@Bean({"open.left","left"})
public TestInterface left() {
    return () -> true;
}

// Child context bean
private static class TestClass {
    @Autowired
    @Qualifier("open.left")  // Should inject "left" bean
    TestInterface right;     // But field name is "right"

    public boolean doit() {
        return right.doItRight();  // Returns false instead of true
    }
}

@Test
public void testInterface() {
    AnnotationConfigApplicationContext subCtx = new AnnotationConfigApplicationContext();
    subCtx.setParent(context);
    subCtx.register(SubConfiguration.class);
    subCtx.refresh();

    // This assertion fails:
    Assertions.assertTrue(subCtx.getBean(TestClass.class).doit());
}

Key elements: 1. Parent context defines two beans of same type with different qualifiers 2. Child context contains a bean with field using @Qualifier but mismatched field name 3. Despite @Qualifier("open.left"), the bean with name matching the field ("right") is injected

A full reproduction case is here: https://github.com/bcubk/spring-qualifier

Is this behaviour as expected or a bug? The qualifier resolution works as expected in a standard context but behaves differently in a parent-child hierarchy.

Environment Spring Boot: 3.x Spring Framework: 6.x Java: 17

Comment From: jhoeller

Are you seeing this on 6.2.x specifically, by any chance? Or on 6.1.x as well? This could be a side effect of the revision for shortcut dependency resolution in 6.2 (#28122).

Generally speaking, the scenario above is somewhat ambiguous since the bean name serves as a qualifier value as well. With open.left via @Qualifier and right via the bean name, it's a matter of precedence which bean is to be matched. And that precedence does not seem to be consistent between the same local context and a parent-child context hierarchy; we'll have a look.

Comment From: jhoeller

It's a 6.2 regression indeed: While qualifier resolution works in parent-child context hierarchies there in the common case, an alias match only works correctly in the local context: that is, the right field name matching the second (alias) name in @Bean({ "open.right","right"}) rather than the first (canonical) name is not treated correctly when a hierarchy is involved. According to my local unit test, it should work correctly if you invert the name declarations - @Bean({ "right","open.right"}) - but I'll have to double-check that with a fix yet.

Comment From: jhoeller

The fix is available in the latest 6.2.6 snapshot now. Please give it an early try if you have the chance!

Comment From: bcubk

Woow, that was fast. @jhoeller, thank you very much. I'll check that ASAP.