Qualifiers aren't captured by AOT in the generated BeanDefinitions classes, leading to failures when running under AOT:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.demo.DemoApplication$RequiresGrpcClient required a bean of type 'com.example.demo.DemoApplication$GrpClient' that could not be found.

The injection point has the following annotations:
    - @com.example.demo.GrpcSpringClient("myclient")

The following candidates were found but could not be injected:
    - User-defined bean


Action:

Consider revisiting the entries above or defining a bean of type 'com.example.demo.DemoApplication$GrpClient' in your configuration.

In our specific case, they're custom qualifier annotations and definitions registered by a registry post-processor. It appears for simple annotated Qualifier beans, the framework is able to fallback and infer the qualifier.

Example project:

https://github.com/DanielThomas/spring-aot-issues/tree/dannyt/qualifier-missing

Run and note the failure:

./gradlew bootJar && java -Dspring.aot.enabled=true -jar build/libs/demo-0.0.1-SNAPSHOT.jar

Comment From: sdeleuze

To be checked if #29709 is related or not.

Comment From: snicoll

In our specific case, they're custom qualifier annotations and definitions registered by a registry post-processor.

Static qualifiers are supported as you've found out. We haven't had a use case of something like this being set programmatically. Thanks for the reproducer!

Comment From: snicoll

It looks like we should support a form of AutowireCandidateQualifier where any value we can handle with AOT is actually written in code. I don't know if we can short-circuit the algorithm that checks for the @Qualifier annotation, but it's worth a try.

Comment From: snicoll

I think I have a fix for this with https://github.com/snicoll/spring-framework/commit/2f41ce6449c60b5a22b87b6a33784c6035499212. Building your reproducer with it adds the following line to the bean definition.

beanDefinition.addQualifier(new AutowireCandidateQualifier("com.example.demo.GrpcSpringClient", "myclient"));

I'd like to spend a bit more time on what we do for @Qualifier and the impact processing those may have. But I am hopeful to get a fix for 6.0.9.