Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisit SpringFactoriesLoader vs. ServiceLoader infrastructure #27753

Closed
bclozel opened this issue Nov 30, 2021 · 2 comments
Closed

Revisit SpringFactoriesLoader vs. ServiceLoader infrastructure #27753

bclozel opened this issue Nov 30, 2021 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: task A general task

Comments

@bclozel
Copy link
Member

bclozel commented Nov 30, 2021

SpringFactoriesLoader has been added in Spring Framework 3.2 (see 988f376) as a simple and internal factory loading mechanism. At the time, the 3.x generation had a Java 1.5 baseline and could not require java.util.ServiceLoader, introduced in Java 1.6.

Over the years, this mechanism has been used more and more by many Spring projects for loading factories. Its contract has also been extended in #15158 for loading factory names and possibly instantiating them "manually" using reflection.
Third party projects are also expected to use the same infrastructure if they want to provide their own support (for example, auto-configurations).

With this issue, the Spring Framework team should discuss whether we should reconsider the current situation, given that:

  1. Spring Framework 6 will have a Java 17 baseline
  2. The Java Platform Module System (JPMS) adds new constraints in this field
  3. The AOT engine (currently in Spring Native, to be ported to Spring Framework) requires specific support for that

Java 17 baseline

ServiceLoader is now mature and has been evolved over the years. The ServiceLoader::stream() method (added in Java 9) allows to iterate over the types without instantiating them. With that, we could probably replace SpringFactoriesLoader.

The Java Platform Module System (JPMS)

Again with Java 9, new mechanisms were added to ServiceLoader to help with the newly introduced module system.
With the JPMS, modules must declare what they export and what they require; without that, they cannot access classes (reflectively or not) if they're not explicitly required by the module descriptor.

With ServiceLoader, any module can declare service implementations. By definition, service clients cannot be aware of all of them and are not in a position to declare them in their module descriptor. ServiceLoader has been improved with new methods and its own provides ... with ... and uses ... keywords in the module descriptor.

SpringFactoriesLoader will hit the JPMS limitations and doesn't currently have any mechanism to address it.

The Spring AOT engine

Spring Native has implemented an AOT engine that pre-processes application configuration and generates Java source files. It greatly helps the GraalVM native compilation phase by making the application startup more explicit and leaner.

Because dynamic class loading and reflection are well-known limitations with native compilation, Spring Native added a specific processing of Spring Factories at build time. This process is listing all factories and their implementations available at build time, and writes a Java source file that explicitly references them so that the GraalVM native static analysis phase discovers them.

Depending on the choice made here, the AOT engine will need to have a SpringFactoriesLoader-specific mechanism or possibly extend the existing ServiceLoader support in GraalVM native.

@bclozel bclozel added type: task A general task in: core Issues in core modules (aop, beans, core, context, expression) status: pending-design-work Needs design work before any code can be developed labels Nov 30, 2021
@bclozel bclozel added this to the 6.0.x milestone Nov 30, 2021
@bclozel bclozel added the theme: aot An issue related to Ahead-of-time processing label Jan 19, 2022
@jhoeller jhoeller modified the milestones: 6.0.x, 6.0.0-M3 Jan 19, 2022
@jhoeller jhoeller changed the title Discuss SpringFactories vs. ServiceLoader infrastructure Revisit SpringFactoriesLoader vs. ServiceLoader infrastructure Jan 19, 2022
@jhoeller jhoeller removed the status: pending-design-work Needs design work before any code can be developed label Jan 19, 2022
@bclozel
Copy link
Member Author

bclozel commented Jan 19, 2022

@jhoeller, @sdeleuze and I have discussed this and came up with the following plan:

  1. The SpringFactoriesLoader#loadFactoryNames contract is just too broad and permissive for AOT processing and enables use cases which are outside of the original scope of this class. We're going to deprecate this method in 6.0.x and remove it completely in the 6.x timeline. See Deprecate SpringFactoriesLoader#loadFactoryNames #27954
  2. SpringFactoriesLoader should be enhanced to allow for static registrations of factories, skipping the loading of spring.factories file and reflection. This should statically populate a "cache" that holds references to factory types and suppliers that instantiate factories implementations. See Support AOT registration of Spring Factories #27955

As part of this issue, we can revisit SpringFactoriesLoader to use ServiceLoader mechanism as one of the supported mechanisms to load factories (static loading for AOT, ServiceLoader and regular spring.factories). This should allow developers to use SpringFactoriesLoader in a JPMS scenario. Note that this issue does not consider moving the existing spring.factories declarations to ServiceLoader metadata.

@jhoeller
Copy link
Contributor

jhoeller commented Oct 5, 2022

Closing this for the time being since we have no immediate need for closer alignment with the ServiceLoader mechanism.

From a core framework perspective, SpringFactoriesLoader is a rather specific mechanism for certain rarely used SPIs (such as BeanInfoFactory) that are meant to be local to the current deployment arrangement.

Broader appeal of SpringFactoriesLoader, potentially with cross-module semantics, depends on usage scenarios outside of the core framework - none of which are currently known to benefit from ServiceLoader alignment.

@jhoeller jhoeller closed this as completed Oct 5, 2022
@jhoeller jhoeller removed this from the 6.0.0-RC1 milestone Oct 5, 2022
@snicoll snicoll closed this as not planned Won't fix, can't repro, duplicate, stale Oct 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) theme: aot An issue related to Ahead-of-time processing type: task A general task
Projects
None yet
Development

No branches or pull requests

3 participants