From d69270266334c21b41c4f5ed4c990ebe06fa7e7a Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 19 Jul 2017 01:28:58 +0200 Subject: [PATCH] DATACMNS-1115 - Improve RepositoryBeanNameGenerator to properly resolve bean names for indexed BeanDefinitions. Previously, RepositoryBeanNameGenerator applied the custom bean name lookup if the BeanDefinition given was not a ScannedGenericBeanDefinition. That in turn had been the case for custom implementation classes that were obtained through classpath scanning. With Spring 5 an index file can be used by the scanner, which in turn will cause AnnotatedGenericBeanDefinition instances being returned. That caused the code path to lookup the first constructor argument to kick in (usually used to obtain the repository interface from repository factory beans) and cause a NullPointerException. We now forward AnnotatedBeanDefinitions as is and only apply the custom lookup for everything else, i.e. the bean definitions used for the factories. --- .../config/RepositoryBeanNameGenerator.java | 18 ++------- .../RepositoryBeanNameGeneratorUnitTests.java | 39 +++++++++++++++---- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java index 7058ee47f..f702e5394 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java @@ -22,7 +22,6 @@ import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefiniti import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.AnnotationBeanNameGenerator; -import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.util.ClassUtils; /** @@ -49,7 +48,9 @@ public class RepositoryBeanNameGenerator { */ public String generateBeanName(BeanDefinition definition) { - AnnotatedBeanDefinition beanDefinition = new AnnotatedGenericBeanDefinition(getRepositoryInterfaceFrom(definition)); + AnnotatedBeanDefinition beanDefinition = definition instanceof AnnotatedBeanDefinition + ? (AnnotatedBeanDefinition) definition + : new AnnotatedGenericBeanDefinition(getRepositoryInterfaceFrom(definition)); return DELEGATE.generateBeanName(beanDefinition, null); } @@ -62,18 +63,7 @@ public class RepositoryBeanNameGenerator { * @return */ private Class getRepositoryInterfaceFrom(BeanDefinition beanDefinition) { - - if (beanDefinition instanceof ScannedGenericBeanDefinition) { - - try { - return ((ScannedGenericBeanDefinition) beanDefinition).resolveBeanClass(beanClassLoader); - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Could not resolve bean class.", e); - } - - } else { - return getRepositoryInterfaceFromFactory(beanDefinition); - } + return getRepositoryInterfaceFromFactory(beanDefinition); } private Class getRepositoryInterfaceFromFactory(BeanDefinition beanDefinition) { diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java index b00bcfead..26018f20d 100755 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java @@ -17,15 +17,20 @@ package org.springframework.data.repository.config; import static org.assertj.core.api.Assertions.*; +import java.io.IOException; + import javax.inject.Named; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanNameGenerator; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.annotation.ScannedGenericBeanDefinition; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; /** @@ -36,12 +41,13 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup */ public class RepositoryBeanNameGeneratorUnitTests { + static final String SAMPLE_IMPLEMENTATION_BEAN_NAME = "repositoryBeanNameGeneratorUnitTests.SomeImplementation"; + RepositoryBeanNameGenerator generator; BeanDefinitionRegistry registry; @Before public void setUp() { - this.generator = new RepositoryBeanNameGenerator(Thread.currentThread().getContextClassLoader()); } @@ -55,6 +61,25 @@ public class RepositoryBeanNameGeneratorUnitTests { assertThat(generator.generateBeanName(getBeanDefinitionFor(AnnotatedInterface.class))).isEqualTo("specialName"); } + @Test // DATACMNS-1115 + public void usesClassNameOfScannedBeanDefinition() throws IOException { + + MetadataReaderFactory factory = new SimpleMetadataReaderFactory(); + MetadataReader reader = factory.getMetadataReader(SomeImplementation.class.getName()); + + BeanDefinition definition = new ScannedGenericBeanDefinition(reader); + + assertThat(generator.generateBeanName(definition)).isEqualTo(SAMPLE_IMPLEMENTATION_BEAN_NAME); + } + + @Test // DATACMNS-1115 + public void usesClassNameOfAnnotatedBeanDefinition() { + + BeanDefinition definition = new AnnotatedGenericBeanDefinition(SomeImplementation.class); + + assertThat(generator.generateBeanName(definition)).isEqualTo(SAMPLE_IMPLEMENTATION_BEAN_NAME); + } + private BeanDefinition getBeanDefinitionFor(Class repositoryInterface) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RepositoryFactoryBeanSupport.class); @@ -62,12 +87,10 @@ public class RepositoryBeanNameGeneratorUnitTests { return builder.getBeanDefinition(); } - interface PlainInterface { - - } + interface PlainInterface {} @Named("specialName") - interface AnnotatedInterface { + interface AnnotatedInterface {} - } + static class SomeImplementation {} }