Skip to content

Align the time at which AOT-based context initialization is performed more closely with the standard case #41600

Open
@wilkinsona

Description

@wilkinsona

We currently add a custom initialiser for AOT and place it first in the application's list of initializers:

if (AotDetector.useGeneratedArtifacts()) {
List<ApplicationContextInitializer<?>> aotInitializers = new ArrayList<>(
initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
if (aotInitializers.isEmpty()) {
String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
if (!ClassUtils.isPresent(initializerClassName, getClassLoader())) {
throw new AotInitializerNotFoundException(this.mainApplicationClass, initializerClassName);
}
aotInitializers.add(AotApplicationContextInitializer.forInitializerClasses(initializerClassName));
}
initializers.removeAll(aotInitializers);
initializers.addAll(0, aotInitializers);
}

A consequence of this is that the use of AOT changes the state of the context when the other initialisers are called. In the standard non-AOT case, the other initializers see an almost empty context that only contains its standard beans. In the AOT case, the other initializers see all of the application's bean. We should try to address this and reduce the difference between the two. The simplest option would be to add the AOT initializer last so that it runs after any other initializers but this doesn't minimise the difference.

In the standard case, the application's beans start to appear in the context when SpringApplication loads the sources. This is done towards the end of prepareContext and immediately before contextLoaded is called on the run listeners. This will typically result in the application's main class being registered as a bean. All of the other beans are then registered as part of refreshing the context which SpringApplication does immediately after calling contextLoaded. In the AOT case, where the initialization happens much earlier, all of the application's beans are visible to:

  • All other context initializers
  • The context prepared callback, including listeners to the ApplicationContextInitializedEvent
  • The context loaded callback, including listeners to the ApplicationPreparedEvent

To minimise the difference between the standard case and the AOT case, I think the AOT initializer should be applied to the context either immediately before contextLoaded is called on the run listeners or immediately before refresh is called on the context. The former will result in the listeners seeing more beans in the context in the AOT case. The latter will result in the listeners not seeing the beans for the application's sources in the AOT case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    theme: aotAn issue related to Ahead-of-time processingtype: enhancementA general enhancement

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions