I'm on a team migrating a relatively large and complex Java application to Kotlin and Spring. It's not feasible to top-down refactor the entire app to Kotlin and dependency injection all at once. To facilitate incremental migration, we capture the ApplicationContext to a static field on startup. From there it can accessed throughout the application. Legacy code can use the ApplicationContext as a service locator via its BeanFactory and ListableBeanFactory methods to access the Spring-ified parts of the application. As the refactoring to DI proceeds, the direct ApplicationContext references are pulled up the call stack until the top-level @Configuration is reached.

We tend to prefer disambiguating beans by type, so T BeanFactory.getBean(Class<T>) is the most commonly used locator method. The problem is, generic types aren't supported. There's ObjectProvider<T> BeanFactory.getBeanProvider(ResolvableType requiredType), but its use involves a bit of boilerplate:

ParameterizedTypeReference<List<List<String>>> parameterizedTypeReference =
        new ParameterizedTypeReference<>() { };

ResolvableType resolvableType =
    ResolvableType.forType(parameterizedTypeReference);

ObjectProvider<List<List<String>>> objectProvider =
    applicationContext.getBeanProvider(resolvableType);

List<List<String>> listOfListOfString =
    objectProvider.getObject();

This can be wrapped up into a utility, but it would be nice if ParameterizedTypeReference overloads of the getBean methods were already available, for example:

List<List<String>> listOfListOfString =
    applicationContext.getBean(new ParameterizedTypeReference<List<List<String>>>() { });

They would also streamline the Kotlin getBean extension implementations with their reified type parameters (see #31439).

I noticed more discussion of ParameterizedTypeReference vs. ResolvableType in #20195. I tend to agree with the comments that the super type token approach of ParameterizedTypeReference makes for the more convenient public API.

I realize using the application context as a service locator is not the primary design intent for the framework, but I'm hoping the migration use case warrants consideration of ParameterizedTypeReference overloads. Presumably they could be added as interface default methods for backwards compatibility.

Comment From: snicoll

Thanks for the suggestion, but that's not the purpose of ParameterizedTypeReference. For what you're trying to accomplish, ResolvableType is the way to go and ObjectProvider provides more control over the result of the lookup. I understand this leads to a bit more code in your end for straightforward use cases, but you can easily craft a couple of methods that provide what you need. Besides, getBean has already a number of overloads so we won't be adding one more for this.

Side note: but for lookups like this, you really should use the BeanFactory rather than having the full method signatures that ApplicationContext brings.