Limit generics length to declared length.

Also, rename method to reflect what it actually returns.
Document generic usage constraints in RepositoryFactoryBeanSupport subclasses.

Closes #3089
This commit is contained in:
Mark Paluch
2024-04-30 15:20:25 +02:00
parent a08a5f753b
commit e2ee018b1a
3 changed files with 49 additions and 19 deletions

View File

@@ -186,7 +186,7 @@ public class RepositoryConfigurationDelegate {
}
RootBeanDefinition beanDefinition = (RootBeanDefinition) definitionBuilder.getBeanDefinition();
beanDefinition.setTargetType(getRepositoryInterface(configuration));
beanDefinition.setTargetType(getRepositoryFactoryBeanType(configuration));
beanDefinition.setResourceDescription(configuration.getResourceDescription());
String beanName = configurationSource.generateBeanName(beanDefinition);
@@ -312,17 +312,16 @@ public class RepositoryConfigurationDelegate {
}
/**
* Returns the repository interface of the given {@link RepositoryConfiguration} as loaded {@link Class}.
* Returns the repository factory bean type from the given {@link RepositoryConfiguration} as loaded {@link Class}.
*
* @param configuration must not be {@literal null}.
* @return can be {@literal null}.
*/
@Nullable
private ResolvableType getRepositoryInterface(RepositoryConfiguration<?> configuration) {
private ResolvableType getRepositoryFactoryBeanType(RepositoryConfiguration<?> configuration) {
String interfaceName = configuration.getRepositoryInterface();
ClassLoader classLoader = resourceLoader.getClassLoader() == null
? ClassUtils.getDefaultClassLoader()
ClassLoader classLoader = resourceLoader.getClassLoader() == null ? ClassUtils.getDefaultClassLoader()
: resourceLoader.getClassLoader();
classLoader = classLoader != null ? classLoader : getClass().getClassLoader();
@@ -346,8 +345,7 @@ public class RepositoryConfigurationDelegate {
ResolvableType[] declaredGenerics = ResolvableType.forClass(factoryBean).getGenerics();
ResolvableType[] parentGenerics = ResolvableType.forClass(RepositoryFactoryBeanSupport.class, factoryBean)
.getGenerics();
List<ResolvableType> resolvedGenerics = new ArrayList<ResolvableType>(factoryBean.getTypeParameters().length);
List<ResolvableType> resolvedGenerics = new ArrayList<>(factoryBean.getTypeParameters().length);
for (int i = 0; i < parentGenerics.length; i++) {
@@ -359,12 +357,11 @@ public class RepositoryConfigurationDelegate {
}
if (resolvedGenerics.size() < declaredGenerics.length) {
for (int j = parentGenerics.length; j < declaredGenerics.length; j++) {
resolvedGenerics.add(declaredGenerics[j]);
}
resolvedGenerics.addAll(Arrays.asList(declaredGenerics).subList(parentGenerics.length, declaredGenerics.length));
}
return ResolvableType.forClassWithGenerics(factoryBean, resolvedGenerics.toArray(ResolvableType[]::new));
return ResolvableType.forClassWithGenerics(factoryBean,
resolvedGenerics.subList(0, declaredGenerics.length).toArray(ResolvableType[]::new));
}
/**

View File

@@ -46,10 +46,17 @@ import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
/**
* Adapter for Springs {@link FactoryBean} interface to allow easy setup of repository factories via Spring
* Adapter for Spring's {@link FactoryBean} interface to allow easy setup of repository factories via Spring
* configuration.
* <p>
* Subclasses may pass-thru generics, provide a fixed domain, provide a fixed identifier type, or provide additional
* generic type parameters. Type parameters must appear in the same order the ones from this class (repository type,
* entity type, identifier type, additional type parameters). Using a different ordering will result in invalid type
* definitions.
*
* @param <T> the type of the repository
* @param <T> the type of the repository.
* @param <S> the entity type.
* @param <ID> the entity identifier type.
* @author Oliver Gierke
* @author Thomas Darimont
* @author Mark Paluch