spring-framework
spring-framework copied to clipboard
Expose a bean instance creator resolver API
We currently resolve the constructor or factory method to use to instantiate a bean using the package private ConstructorResolver
class. When processing a BeanFactory
at build-time, we need to retain that information (without instantiating the bean) so that we lower reflection and processing at runtime.
Right now, ConstructorResolver
:
- Detect and instantiate the
Constructor
to use. - Detect the factory method to use and set some additional metadata in the bean definition
- Instantiate the bean using the state of the bean definition
Rather than returning BeanWrapper
we could return an object that provides the metadata that we need and wrap the instantiation call for the regular runtime behavior. However, the difference between constructor and factory method is annoying as I'd rather have a consistent API for both.
It is also unknown how we'd store the resolved arguments or if we'd need to.
FTR we have a very hackish/temporary version in the meantime in DefaultBeanRegistrationContributionProvider
.
On a related note, after #28414, the ConstructorOrFactoryMethodResolver
class re-implementing constructor resolution at this point refers to the @Autowired
annotation directly, creating a package cycle between beans.factory.aot
and beans.factory.annotation
. This should be resolved along the proposed reusable constructor resolution algorithm here.
Juergen and I brainstormed about this one today and we're thinking about an API that would provide a richer model to account, namely, for generic constructor argument values.
Given a BeanDefinition
, the resolver would return:
- The
Executable
to use - A view over the arguments that have been "pre-converted" if necessary. This includes
TypeStringValue
that exposes a rawString
value with an optional type that should be taken into account to determine the constructor anyway. There are other cases where the input value doesn't strictly match the parameter type, including for indexed constructor arguments. - Potentially a way to determine that an argument has to be autowired.
Based on this model we could generate code so that a ConstructorArgumentValue
is already in the expected type. If a generic constructor argument has been resolved, it becomes indexed rather so that code instantiation is as straightforward as possible.
A further refinement is the case where all the arguments are known upfront, avoiding the use of AutowiredArguments
altogether.
There is such an example of such a generic argument in #29087.
Regarding 2. I should add some sort of SPI for this would be very much welcome as this could be reused transparently for PropertyValues
. The conversion for the expected type can happen and it could handle TypeStringValue
transparently as well.
I'm narrowing the scope of this ticket for our immediate purposes in 6.0, namely merging AOT constructor and factory method resolution into ConstructorResolver
in the beans.factory.support
package. This moves related code into the same class, unifies candidate determination for constructors and factory methods, and gets rid of the package cycle around the hard-coded Autowired
annotation check (which is implicitly coming from AutowiredAnnotationBeanPostProcessor
via the determineCandidateConstructors
SPI now). The API entry point for AOT pre-resolution purposes is in RegisteredBean
now.
Follow-up work might happen before GA still or afterwards in the 6.0.x line, ideally without affecting applications or the rest of the portfolio.
@jhoeller I didn't see a follow-up issue for the argument resolution that is quite important for XML-based scenarios. I've created another issue.
HI, do you have a link to the follow up issue, please so I can follow it?
With the latest snapshots I still see the issue as I raised under https://github.com/spring-projects/spring-framework/issues/29052 when trying to compile as native.
Alright. Please create a separate issue and share a small sample we can use to reproduce.