diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideParser.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideParser.java index 4b89d99a82..b09cb0fa1a 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideParser.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideParser.java @@ -17,21 +17,17 @@ package org.springframework.test.context.bean.override; import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; -import org.springframework.beans.factory.support.BeanDefinitionValidationException; +import org.springframework.beans.BeanUtils; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import static org.springframework.core.annotation.MergedAnnotations.SearchStrategy.DIRECT; @@ -41,6 +37,7 @@ import static org.springframework.core.annotation.MergedAnnotations.SearchStrate * on fields of a given class and creates {@link OverrideMetadata} accordingly. * * @author Simon Baslé + * @author Sam Brannen * @since 6.2 */ class BeanOverrideParser { @@ -102,41 +99,21 @@ class BeanOverrideParser { .map(mergedAnnotation -> { MergedAnnotation metaSource = mergedAnnotation.getMetaSource(); Assert.notNull(metaSource, "@BeanOverride annotation must be meta-present"); - return new AnnotationPair(metaSource.synthesize(), mergedAnnotation); + return new AnnotationPair(metaSource.synthesize(), mergedAnnotation.synthesize()); }) .forEach(pair -> { - BeanOverride beanOverride = pair.mergedAnnotation().synthesize(); - BeanOverrideProcessor processor = getProcessorInstance(beanOverride.value()); - if (processor == null) { - return; - } - ResolvableType typeToOverride = processor.getOrDeduceType(field, pair.annotation(), source); + BeanOverrideProcessor processor = BeanUtils.instantiateClass(pair.beanOverride.value()); + ResolvableType typeToOverride = processor.getOrDeduceType(field, pair.composedAnnotation, source); Assert.state(overrideAnnotationFound.compareAndSet(false, true), () -> "Multiple @BeanOverride annotations found on field: " + field); - OverrideMetadata metadata = processor.createMetadata(field, pair.annotation(), typeToOverride); + OverrideMetadata metadata = processor.createMetadata(field, pair.composedAnnotation, typeToOverride); boolean isNewDefinition = this.parsedMetadata.add(metadata); Assert.state(isNewDefinition, () -> "Duplicate " + metadata.getBeanOverrideDescription() + " OverrideMetadata: " + metadata); }); } - @Nullable - private BeanOverrideProcessor getProcessorInstance(Class processorClass) { - Constructor constructor = ClassUtils.getConstructorIfAvailable(processorClass); - if (constructor != null) { - try { - ReflectionUtils.makeAccessible(constructor); - return constructor.newInstance(); - } - catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { - throw new BeanDefinitionValidationException( - "Failed to instantiate BeanOverrideProcessor of type " + processorClass.getName(), ex); - } - } - return null; - } - - private record AnnotationPair(Annotation annotation, MergedAnnotation mergedAnnotation) {} + private record AnnotationPair(Annotation composedAnnotation, BeanOverride beanOverride) {} } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideParserTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideParserTests.java index 3c0bf9c20e..099d7d7cf3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideParserTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideParserTests.java @@ -26,7 +26,6 @@ import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatRuntimeException; -import static org.springframework.test.context.bean.override.example.ExampleBeanOverrideProcessor.DUPLICATE_TRIGGER; /** * Unit tests for {@link BeanOverrideParser}. @@ -35,6 +34,9 @@ import static org.springframework.test.context.bean.override.example.ExampleBean */ class BeanOverrideParserTests { + // Copy of ExampleBeanOverrideProcessor.DUPLICATE_TRIGGER which is package-private. + private static final String DUPLICATE_TRIGGER = "DUPLICATE"; + private final BeanOverrideParser parser = new BeanOverrideParser(); diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/example/ExampleBeanOverrideProcessor.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/example/ExampleBeanOverrideProcessor.java index e92c483101..294da24f98 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/example/ExampleBeanOverrideProcessor.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/example/ExampleBeanOverrideProcessor.java @@ -23,7 +23,10 @@ import org.springframework.core.ResolvableType; import org.springframework.test.context.bean.override.BeanOverrideProcessor; import org.springframework.test.context.bean.override.OverrideMetadata; -public class ExampleBeanOverrideProcessor implements BeanOverrideProcessor { +// Intentionally NOT public +class ExampleBeanOverrideProcessor implements BeanOverrideProcessor { + + static final String DUPLICATE_TRIGGER = "DUPLICATE"; private static final TestOverrideMetadata CONSTANT = new TestOverrideMetadata() { @Override @@ -32,8 +35,6 @@ public class ExampleBeanOverrideProcessor implements BeanOverrideProcessor { } }; - public static final String DUPLICATE_TRIGGER = "CONSTANT"; - @Override public OverrideMetadata createMetadata(Field field, Annotation overrideAnnotation, ResolvableType typeToOverride) { if (!(overrideAnnotation instanceof ExampleBeanOverrideAnnotation annotation)) { diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/example/TestOverrideMetadata.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/example/TestOverrideMetadata.java index 124c1eea61..542217877c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/example/TestOverrideMetadata.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/example/TestOverrideMetadata.java @@ -32,7 +32,7 @@ import org.springframework.util.StringUtils; import static org.springframework.test.context.bean.override.example.ExampleBeanOverrideAnnotation.DEFAULT_VALUE; -public class TestOverrideMetadata extends OverrideMetadata { +class TestOverrideMetadata extends OverrideMetadata { @Nullable private final Method method;