spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Expose a bean instance creator resolver API

Open snicoll opened this issue 3 years ago • 4 comments

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.

snicoll avatar Jan 11 '22 15:01 snicoll

FTR we have a very hackish/temporary version in the meantime in DefaultBeanRegistrationContributionProvider.

snicoll avatar Mar 09 '22 10:03 snicoll

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.

jhoeller avatar May 12 '22 11:05 jhoeller

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:

  1. The Executable to use
  2. A view over the arguments that have been "pre-converted" if necessary. This includes TypeStringValue that exposes a raw String 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.
  3. 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.

snicoll avatar Sep 09 '22 14:09 snicoll

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.

snicoll avatar Sep 14 '22 11:09 snicoll

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 avatar Oct 05 '22 13:10 jhoeller

@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.

snicoll avatar Oct 08 '22 08:10 snicoll

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.

CynanX avatar Oct 31 '22 08:10 CynanX

Alright. Please create a separate issue and share a small sample we can use to reproduce.

snicoll avatar Oct 31 '22 09:10 snicoll