RootBeanDefinition.getSource()
is null
in spring-aot-mode
.
The simplest example
https://github.com/wangliang181230/example__spring-projects_spring-framework_issue-30017
The classes
public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanDefinition.getSource() == null) {
throw new BeanDefinitionValidationException("The source must not be null");
}
// Do something, for example: get an annotation from the MethodMetadata.
}
}
Reproduce
- clone the sample application.
mvn clean install -Pnative
.- Run the test
ExampleApplicationTest
, and it will throw an exception. SeeMyMergedBeanDefinitionPostProcessor
.
env and versions:
- OS:
Windows 10
- GraalVM: graalvm-ce-java17-22.3.1 Windows (amd64)
- Spring Boot:
3.0.2
- native-maven-plugin:
0.9.20
Comment From: sbrannen
getSource()
is permitted to return null
, so it's not necessarily an error state.
Though I suppose you're expecting a source to be available in AOT mode if it's available in standard mode.
As a side note, are you aware of the org.springframework.beans.factory.ListableBeanFactory.findAnnotationOnBean(String, Class<A>)
method?
Comment From: wangliang181230
getSource()
is permitted to returnnull
, so it's not necessarily an error state.
If it is not a bug, I want to know why the MethodMetadata
is not loaded in AOT mode?
Though I suppose you're expecting a source to be available in AOT mode if it's available in standard mode.
If AOT mode and standard mode can be consistent, it is best.
As a side note, are you aware of the
org.springframework.beans.factory.ListableBeanFactory.findAnnotationOnBean(String, Class<A>)
method?
Sorry, I don't know this method. Let me see what it is.
Comment From: sbrannen
If it is not a bug, I want to know why the
MethodMetadata
is not loaded in AOT mode?
It certainly seems to be a gap in the AOT support which could potentially be considered a bug. Someone in the team will need to take a closer look at the code in question to determine that.
If AOT mode and standard mode can be consistent, it is best.
Yes, I agree with that. Whenever possible, we aim for AOT mode semantics to align with standard Spring runtime semantics.
As a side note, are you aware of the
org.springframework.beans.factory.ListableBeanFactory.findAnnotationOnBean(String, Class<A>)
method?Sorry, I don't know this method. Let me see what it is.
I mentioned that, because your example application looks up annotations on the @Bean
methods, and ListableBeanFactory.findAnnotationOnBean
is typically the preferred mechanism for achieving that.
In other words, if your use case only involves looking up annotations on bean classes and @Bean
methods, you should theoretically be able to rework your MergedBeanDefinitionPostProcessor
implementation so that it:
- implements
BeanFactoryAware
- checks that the supplied
BeanFactory
is aninstanceof ListableBeanFactory
- casts to
ListableBeanFactory
- uses
ListableBeanFactory.findAnnotationOnBean
to find annotations instead of relying on thebeanDefinition.getSource()
being an instance ofStandardMethodMetadata
.
Does that suit your needs as an interim workaround?
Comment From: wangliang181230
I mentioned that, because your example application looks up annotations on the
@Bean
methods, andListableBeanFactory.findAnnotationOnBean
is typically the preferred mechanism for achieving that.In other words, if your use case only involves looking up annotations on bean classes and
@Bean
methods, you should theoretically be able to rework yourMergedBeanDefinitionPostProcessor
implementation so that it:
- implements
BeanFactoryAware
- checks that the supplied
BeanFactory
is aninstanceof ListableBeanFactory
- casts to
ListableBeanFactory
- uses
ListableBeanFactory.findAnnotationOnBean
to find annotations instead of relying on thebeanDefinition.getSource()
being an instance ofStandardMethodMetadata
.Does that make suit your needs as an interim workaround?
Oh, yes, it looks better. I will try it. Thank you very much.
Comment From: snicoll
In AOT mode, there is no notion of @Configuration
class anymore. Some components that are discovered by classpath scanning could have a specific BeanDefinition
-subtype that is "lost" in AOT mode as the scanning does not occur.
As discussed here already, your current code should not rely on getSource()
.