Make resolution algorithm of ConnectionDetailsFactory more explicit

This commit moves the resolution check for ConnectionDetailsFactory
to a dedicated method to make it more clear that it is meant to verify
that the implementation is resolved and can be loaded from the
classpath.

The previous algorithm relied on a behavior of ResolvableType that only
resolves the first level generics. Further improvements in Spring
Framework 6.2 make this check invalid as some implementations use a
Container that can hold a nested generic.

See gh-39737
This commit is contained in:
Stéphane Nicoll 2024-02-23 09:17:01 +01:00 committed by Scott Frederick
parent 54cdc83337
commit c259a673d3

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -122,13 +122,30 @@ public class ConnectionDetailsFactories {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <S, D extends ConnectionDetails> Registration<S, D> get(ConnectionDetailsFactory<S, D> factory) { private static <S, D extends ConnectionDetails> Registration<S, D> get(ConnectionDetailsFactory<S, D> factory) {
ResolvableType type = ResolvableType.forClass(ConnectionDetailsFactory.class, factory.getClass()); ResolvableType type = ResolvableType.forClass(ConnectionDetailsFactory.class, factory.getClass());
if (!type.hasUnresolvableGenerics()) { Class<?>[] generics = resolveGenerics(type);
Class<?>[] generics = type.resolveGenerics(); if (generics != null) {
return new Registration<>((Class<S>) generics[0], (Class<D>) generics[1], factory); return new Registration<>((Class<S>) generics[0], (Class<D>) generics[1], factory);
} }
return null; return null;
} }
/**
* Resolve the generics of the given {@link ResolvableType} or {@code null} if any
* of them cannot be resolved.
* @param type the type to inspect
* @return the resolved generics if they can be loaded from the classpath,
* {@code null} otherwise
*/
private static Class<?>[] resolveGenerics(ResolvableType type) {
Class<?>[] resolvedGenerics = type.resolveGenerics();
for (Class<?> genericRawType : resolvedGenerics) {
if (genericRawType == null) {
return null;
}
}
return resolvedGenerics;
}
} }
} }