Polish "Bean Overriding in Tests" support

This commit is contained in:
Sam Brannen 2024-04-16 17:08:15 +02:00
parent ce8758b83c
commit 8727d723f3
14 changed files with 134 additions and 123 deletions

View File

@ -134,13 +134,13 @@
**** xref:testing/testcontext-framework/ctx-management/failure-threshold.adoc[]
**** xref:testing/testcontext-framework/ctx-management/hierarchies.adoc[]
*** xref:testing/testcontext-framework/fixture-di.adoc[]
*** xref:testing/testcontext-framework/bean-overriding.adoc[]
*** xref:testing/testcontext-framework/web-scoped-beans.adoc[]
*** xref:testing/testcontext-framework/tx.adoc[]
*** xref:testing/testcontext-framework/executing-sql.adoc[]
*** xref:testing/testcontext-framework/parallel-test-execution.adoc[]
*** xref:testing/testcontext-framework/support-classes.adoc[]
*** xref:testing/testcontext-framework/aot.adoc[]
*** xref:testing/testcontext-framework/bean-overriding.adoc[]
** xref:testing/webtestclient.adoc[]
** xref:testing/spring-mvc-test-framework.adoc[]
*** xref:testing/spring-mvc-test-framework/server.adoc[]
@ -172,6 +172,8 @@
***** xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[]
***** xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testbean.adoc[]
***** xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[]
***** xref:testing/annotations/integration-spring/annotation-dirtiescontext.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testexecutionlisteners.adoc[]
***** xref:testing/annotations/integration-spring/annotation-recordapplicationevents.adoc[]
@ -184,8 +186,6 @@
***** xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[]
***** xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[]
***** xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[]
***** xref:testing/annotations/integration-spring/annotation-testbean.adoc[]
***** xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[]
**** xref:testing/annotations/integration-junit4.adoc[]
**** xref:testing/annotations/integration-junit-jupiter.adoc[]
**** xref:testing/annotations/integration-meta.adoc[]

View File

@ -16,6 +16,8 @@ Spring's testing annotations include the following:
* xref:testing/annotations/integration-spring/annotation-activeprofiles.adoc[`@ActiveProfiles`]
* xref:testing/annotations/integration-spring/annotation-testpropertysource.adoc[`@TestPropertySource`]
* xref:testing/annotations/integration-spring/annotation-dynamicpropertysource.adoc[`@DynamicPropertySource`]
* xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`]
* xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and `@MockitoSpyBean`]
* xref:testing/annotations/integration-spring/annotation-dirtiescontext.adoc[`@DirtiesContext`]
* xref:testing/annotations/integration-spring/annotation-testexecutionlisteners.adoc[`@TestExecutionListeners`]
* xref:testing/annotations/integration-spring/annotation-recordapplicationevents.adoc[`@RecordApplicationEvents`]
@ -28,6 +30,4 @@ Spring's testing annotations include the following:
* xref:testing/annotations/integration-spring/annotation-sqlmergemode.adoc[`@SqlMergeMode`]
* xref:testing/annotations/integration-spring/annotation-sqlgroup.adoc[`@SqlGroup`]
* xref:testing/annotations/integration-spring/annotation-disabledinaotmode.adoc[`@DisabledInAotMode`]
* xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`]
* xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and `@MockitoSpyBean`]

View File

@ -1,24 +1,24 @@
[[spring-testing-annotation-beanoverriding-mockitobean]]
= `@MockitoBean` and `@MockitoSpyBean`
`@MockitoBean` and `@MockitoSpyBean` are used on a test class field to override a bean
with a mocking and spying instance, respectively. In the later case, the original bean
definition is not replaced but instead an early instance is captured and wrapped by the
spy.
`@MockitoBean` and `@MockitoSpyBean` are used on test class fields to override beans in
the test's `ApplicationContext` with a Mockito mock or spy, respectively. In the latter
case, the original bean definition is not replaced, but instead an early instance of the
bean is captured and wrapped by the spy.
By default, the name of the bean to override is derived from the annotated field's name,
but both annotations allows for a specific `name` to be provided. Each annotation also
but both annotations allow for a specific `name` to be provided. Each annotation also
defines Mockito-specific attributes to fine-tune the mocking details.
The `@MockitoBean` annotation uses the `CREATE_OR_REPLACE_DEFINITION`
The `@MockitoBean` annotation uses the `REPLACE_OR_CREATE_DEFINITION`
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
The `@MockitoSpyBean` annotation uses the `WRAP_EARLY_BEAN`
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy]
The `@MockitoSpyBean` annotation uses the `WRAP_BEAN`
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy],
and the original instance is wrapped in a Mockito spy.
The following example shows how to configure the bean name for both `@MockitoBean` and
`@MockitoSpyBean` annotations:
The following example shows how to configure the bean name via `@MockitoBean` and
`@MockitoSpyBean`:
[tabs]
======
@ -27,6 +27,7 @@ Java::
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class OverrideBeanTests {
@MockitoBean(name = "service1") // <1>
private CustomService mockService;
@ -36,7 +37,7 @@ Java::
// test case body...
}
----
<1> Mark `mockService` as a Mockito mock override of bean `service1` in this test class
<2> Mark `spyService` as a Mockito spy override of bean `service2` in this test class
<3> Both fields will be injected with the Mockito values (the mock and the spy respectively)
======
<1> Mark `mockService` as a Mockito mock override of bean `service1` in this test class.
<2> Mark `spyService` as a Mockito spy override of bean `service2` in this test class.
<3> The fields will be injected with the Mockito mock and spy, respectively.
======

View File

@ -1,17 +1,18 @@
[[spring-testing-annotation-beanoverriding-testbean]]
= `@TestBean`
`@TestBean` is used on a test class field to override a specific bean with an instance
provided by a conventionally named static factory method.
`@TestBean` is used on a test class field to override a specific bean in the test's
`ApplicationContext` with an instance provided by a conventionally named static factory
method.
By default, the bean name and the associated factory method name are derived from the
annotated field's name but the annotation allows for specific values to be provided.
annotated field's name, but the annotation allows for specific values to be provided.
The `@TestBean` annotation uses the `REPLACE_DEFINITION`
xref:testing/testcontext-framework/bean-overriding.adoc#spring-testing-beanoverriding-extending[strategy for test bean overriding].
The following example shows how to fully configure the `@TestBean` annotation, with
explicit values equivalent to the default:
explicit values equivalent to the defaults:
[tabs]
======
@ -30,10 +31,9 @@ Java::
}
}
----
<1> Mark a field for bean overriding in this test class
<2> The result of this static method will be used as the instance and injected into the field
<1> Mark a field for bean overriding in this test class.
<2> The result of this static method will be used as the instance and injected into the field.
======
NOTE: The method to invoke is searched in the test class and any enclosing class it might
have, as well as its hierarchy. This typically allows nested test class to rely on the
factory method in the root test class.
NOTE: Spring searches for the factory method to invoke in the test class, in the test
class hierarchy, and in the enclosing class hierarchy for a `@Nested` test class.

View File

@ -1,53 +1,67 @@
[[spring-testing-beanoverriding]]
[[testcontext-bean-overriding]]
= Bean Overriding in Tests
Bean Overriding in Tests refers to the ability to override specific beans in the Context
for a test class, by annotating one or more fields in said test class.
Bean overriding in tests refers to the ability to override specific beans in the
`ApplicationContext` for a test class, by annotating one or more fields in the test class.
NOTE: This is intended as a less risky alternative to the practice of registering a bean via
`@Bean` with the `DefaultListableBeanFactory` `setAllowBeanDefinitionOverriding` set to
`true`.
NOTE: This feature is intended as a less risky alternative to the practice of registering
a bean via `@Bean` with the `DefaultListableBeanFactory`
`setAllowBeanDefinitionOverriding` flag set to `true`.
The Spring Testing Framework provides two sets of annotations:
xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`],
xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and
`@MockitoSpyBean`]. The former relies purely on Spring, while the later set relies on
the https://site.mockito.org/[Mockito] third party library.
The Spring TestContext framework provides two sets of annotations for bean overriding.
[[spring-testing-beanoverriding-extending]]
== Extending bean override with a custom annotation
* xref:testing/annotations/integration-spring/annotation-testbean.adoc[`@TestBean`]
* xref:testing/annotations/integration-spring/annotation-mockitobean.adoc[`@MockitoBean` and `@MockitoSpyBean`]
The three annotations mentioned above build upon the `@BeanOverride` meta-annotation
and associated infrastructure, which allows to define custom bean overriding variants.
The former relies purely on Spring, while the latter set relies on the
https://site.mockito.org/[Mockito] third-party library.
To create an extension, the following is needed:
[[testcontext-bean-overriding-custom]]
== Custom Bean Override Support
- An annotation meta-annotated with `@BeanOverride` that defines the
`BeanOverrideProcessor` to use.
- The `BeanOverrideProcessor` implementation itself.
- One or more concrete `OverrideMetadata` implementations provided by the processor.
The three annotations mentioned above build upon the `@BeanOverride` meta-annotation and
associated infrastructure, which allows one to define custom bean overriding variants.
The Spring TestContext Framework includes infrastructure classes that support bean
overriding: a `BeanFactoryPostProcessor`, a `TestExecutionListener` and a
`ContextCustomizerFactory`.
The later two are automatically registered via the Spring TestContext Framework
`spring.factories` file, and are responsible for setting up the rest of the infrastructure.
To create custom bean override support, the following is needed:
The test classes are parsed looking for any field meta-annotated with `@BeanOverride`,
instantiating the relevant `BeanOverrideProcessor` in order to register an
`OverrideMetadata`.
* An annotation meta-annotated with `@BeanOverride` that defines the
`BeanOverrideProcessor` to use
* A custom `BeanOverrideProcessor` implementation
* One or more concrete `OverrideMetadata` implementations provided by the processor
Then the `BeanOverrideBeanFactoryPostProcessor` will use that information to alter the
context, registering and replacing bean definitions as defined by each metadata
`BeanOverrideStrategy`:
The Spring TestContext framework includes implementations of the following APIs that
support bean overriding and are responsible for setting up the rest of the infrastructure.
- `REPLACE_DEFINITION`: replaces the bean definition. If it is not present in the
context, an exception is thrown.
- `CREATE_OR_REPLACE_DEFINITION`: replaces the bean definition if the bean definition
does not exist, or create one if it is not.
- `WRAP_BEAN`: get the original instance early so that it can be wrapped.
* a `BeanFactoryPostProcessor`
* a `ContextCustomizerFactory`
* a `TestExecutionListener`
NOTE: The Bean Overriding infrastructure does not include any bean resolution step,
unlike an `@Autowired`-annotated field for instance. As such, the name of the bean to
override must be somehow provided to or computed by the `BeanOverrideProcessor`.
Typically, the user provides the name one way or the other.
The `spring-test` module registers implementations of the latter two
(`BeanOverrideContextCustomizerFactory` and `BeanOverrideTestExecutionListener`) in its
{spring-framework-code}/spring-test/src/main/resources/META-INF/spring.factories[`META-INF/spring.factories`
properties file].
The bean overriding infrastructure searches in test classes for any field meta-annotated
with `@BeanOverride` and instantiates the corresponding `BeanOverrideProcessor` which is
responsible for registering appropriate `OverrideMetadata`.
The internal `BeanOverrideBeanFactoryPostProcessor` then uses that information to alter
the test's `ApplicationContext` by registering and replacing bean definitions as defined
by the corresponding `BeanOverrideStrategy`:
* `REPLACE_DEFINITION`: Replaces the bean definition. Throws an exception if a
corresponding bean definition does not exist.
* `REPLACE_OR_CREATE_DEFINITION`: Replaces the bean definition if it exists. Creates a
new bean definition if a corresponding bean definition does not exist.
* `WRAP_BEAN`: Retrieves the original bean instance and wraps it.
[NOTE]
====
In contrast to Spring's autowiring mechanism (for example, resolution of an `@Autowired`
field), the bean overriding infrastructure in the TestContext framework does not perform
any heuristics to locate a bean. Instead, the name of the bean to override must be
explicitly provided to or computed by the `BeanOverrideProcessor`.
Typically, the user provides the bean name via a custom annotation, or the
`BeanOverrideProcessor` determines the bean name based on some convention.
====

View File

@ -22,25 +22,23 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mark an annotation as eligible for Bean Override processing.
* Mark a composed annotation as eligible for Bean Override processing.
*
* <p>Specifying this annotation triggers the defined {@link BeanOverrideProcessor}
* <p>Specifying this annotation triggers the configured {@link BeanOverrideProcessor}
* which must be capable of handling the composed annotation and its attributes.
*
* <p>The composed annotation is meant to be detected on fields only so it is
* expected that it has a {@code Target} of {@link ElementType#FIELD FIELD}.
* <p>Since the composed annotation should only be applied to fields, it is
* expected that it has a {@link Target} of {@link ElementType#FIELD FIELD}.
*
* @author Simon Baslé
* @since 6.2
* @see BeanOverrideBeanFactoryPostProcessor
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface BeanOverride {
/**
* The {@link BeanOverrideProcessor} implementation to trigger against
* the composed annotation.
* The {@link BeanOverrideProcessor} implementation to use.
*/
Class<? extends BeanOverrideProcessor> value();

View File

@ -41,7 +41,7 @@ import org.springframework.util.StringUtils;
/**
* A {@link BeanFactoryPostProcessor} implementation that processes test classes
* and adapt the {@link BeanFactory} for any {@link BeanOverride} it may define.
* and adapts the {@link BeanFactory} for any {@link BeanOverride} it may define.
*
* <p>A set of classes from which to parse {@link OverrideMetadata} must be
* provided to this processor. Each test class is expected to use any
@ -51,7 +51,7 @@ import org.springframework.util.StringUtils;
*
* <p>The provided classes are fully parsed at creation to build a metadata set.
* This processor implements several {@link BeanOverrideStrategy overriding
* strategy} and chooses the correct one according to each override metadata
* strategies} and chooses the correct one according to each override metadata's
* {@link OverrideMetadata#getStrategy()} method. Additionally, it provides
* support for injecting the overridden bean instances into their corresponding
* annotated {@link Field fields}.
@ -61,7 +61,6 @@ import org.springframework.util.StringUtils;
*/
class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {
private final BeanOverrideRegistrar overrideRegistrar;
@ -195,14 +194,13 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
static final class WrapEarlyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
PriorityOrdered {
private final BeanOverrideRegistrar overrideRegistrar;
private final Map<String, Object> earlyReferences = new ConcurrentHashMap<>(16);
private final Map<String, Object> earlyReferences;
private final BeanOverrideRegistrar overrideRegistrar;
private WrapEarlyBeanPostProcessor(BeanOverrideRegistrar registrar) {
this.overrideRegistrar = registrar;
this.earlyReferences = new ConcurrentHashMap<>(16);
}

View File

@ -69,6 +69,7 @@ class BeanOverrideContextCustomizer implements ContextCustomizer {
private static void addInfrastructureBeanDefinition(BeanDefinitionRegistry registry,
Class<?> clazz, String beanName, Consumer<ConstructorArgumentValues> constructorArgumentsConsumer) {
if (!registry.containsBeanDefinition(beanName)) {
RootBeanDefinition definition = new RootBeanDefinition(clazz);
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

View File

@ -84,12 +84,11 @@ abstract class BeanOverrideParsingUtils {
private static void parseField(Field field, Class<?> testClass, Set<OverrideMetadata> metadataSet) {
AtomicBoolean overrideAnnotationFound = new AtomicBoolean();
MergedAnnotations.from(field, DIRECT).stream(BeanOverride.class).forEach(mergedAnnotation -> {
Assert.state(mergedAnnotation.isMetaPresent(), "@BeanOverride annotation must be meta-present");
MergedAnnotation<?> metaSource = mergedAnnotation.getMetaSource();
Assert.state(metaSource != null, "@BeanOverride annotation must be meta-present");
BeanOverride beanOverride = mergedAnnotation.synthesize();
BeanOverrideProcessor processor = BeanUtils.instantiateClass(beanOverride.value());
MergedAnnotation<?> metaSource = mergedAnnotation.getMetaSource();
Assert.state(metaSource != null, "Meta-annotation source must not be null");
Annotation composedAnnotation = metaSource.synthesize();
Assert.state(overrideAnnotationFound.compareAndSet(false, true),

View File

@ -20,11 +20,11 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* Strategy interface for Bean Override processing, providing an
* Strategy interface for Bean Override processing, providing
* {@link OverrideMetadata} that drives how the target bean is overridden.
*
* <p>At least one composed annotations meta-annotated with
* {@link BeanOverride @BeanOverride}) is a companion of this processor and
* <p>At least one composed annotation that is meta-annotated with
* {@link BeanOverride @BeanOverride} must be a companion of this processor and
* may provide additional user settings that drive how the concrete
* {@link OverrideMetadata} is configured.
*

View File

@ -41,23 +41,22 @@ import org.springframework.util.StringUtils;
*/
class BeanOverrideRegistrar implements BeanFactoryAware {
private final Map<OverrideMetadata, String> beanNameRegistry;
private final Map<OverrideMetadata, String> beanNameRegistry = new HashMap<>();
private final Map<String, OverrideMetadata> earlyOverrideMetadata;
private final Map<String, OverrideMetadata> earlyOverrideMetadata = new HashMap<>();
private final Set<OverrideMetadata> overrideMetadata;
@Nullable
private ConfigurableBeanFactory beanFactory;
/**
* Create a new registrar and immediately parse the provided classes.
* @param classesToParse the initial set of classes that have been
* detected to contain bean overriding annotations
*/
BeanOverrideRegistrar(Set<Class<?>> classesToParse) {
this.beanNameRegistry = new HashMap<>();
this.earlyOverrideMetadata = new HashMap<>();
this.overrideMetadata = BeanOverrideParsingUtils.parse(classesToParse);
}
@ -71,7 +70,7 @@ class BeanOverrideRegistrar implements BeanFactoryAware {
}
/**
* Return the detected {@link OverrideMetadata} instances.
* Get the detected {@link OverrideMetadata} instances.
*/
Set<OverrideMetadata> getOverrideMetadata() {
return this.overrideMetadata;
@ -85,16 +84,16 @@ class BeanOverrideRegistrar implements BeanFactoryAware {
Object wrapIfNecessary(Object bean, String beanName) throws BeansException {
OverrideMetadata metadata = this.earlyOverrideMetadata.get(beanName);
if (metadata != null && metadata.getStrategy() == BeanOverrideStrategy.WRAP_BEAN) {
bean = metadata.createOverride(beanName, null, bean);
Assert.state(this.beanFactory != null, "ConfigurableBeanFactory must not be null");
bean = metadata.createOverride(beanName, null, bean);
metadata.track(bean, this.beanFactory);
}
return bean;
}
/**
* Register the provided {@link OverrideMetadata} and associate it with a
* {@code beanName}.
* Register the provided {@link OverrideMetadata} and associate it with the
* supplied {@code beanName}.
*/
void registerNameForMetadata(OverrideMetadata metadata, String beanName) {
this.beanNameRegistry.put(metadata, beanName);
@ -119,7 +118,7 @@ class BeanOverrideRegistrar implements BeanFactoryAware {
try {
ReflectionUtils.makeAccessible(field);
Object existingValue = ReflectionUtils.getField(field, target);
Assert.state(this.beanFactory != null, "beanFactory must not be null");
Assert.state(this.beanFactory != null, "ConfigurableBeanFactory must not be null");
Object bean = this.beanFactory.getBean(beanName, field.getType());
if (existingValue == bean) {
return;

View File

@ -35,7 +35,7 @@ public enum BeanOverrideStrategy {
/**
* Replace or create a given bean definition, immediately preparing a
* singleton instance.
* <p>Contrary to {@link #REPLACE_DEFINITION} this create a new bean
* <p>Contrary to {@link #REPLACE_DEFINITION}, this creates a new bean
* definition if the target bean definition does not exist rather than
* failing.
*/
@ -43,8 +43,9 @@ public enum BeanOverrideStrategy {
/**
* Intercept and process an early bean reference rather than a bean
* definition, allowing variants of bean overriding to wrap the instance.
* For instance, to delegate to actual methods in the context of a mocking "spy".
* definition, allowing variants of bean overriding to wrap the instance
* &mdash; for example, to delegate to actual methods in the context of a
* mocking "spy".
*/
WRAP_BEAN

View File

@ -20,15 +20,13 @@ import java.lang.reflect.Field;
import java.util.function.BiConsumer;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.util.ReflectionUtils;
/**
* {@link TestExecutionListener} implementation that enables Bean Override
* support in tests, injecting overridden beans in appropriate fields of the
* test instance.
* {@code TestExecutionListener} that enables Bean Override support in tests,
* injecting overridden beans in appropriate fields of the test instance.
*
* @author Simon Baslé
* @since 6.2
@ -54,9 +52,9 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
}
/**
* Process the test instance and make sure that flagged fields for bean
* overriding are processed. Each field get is value updated with the
* overridden bean instance.
* Process the test instance and make sure that fields flagged for bean
* overriding are processed.
* <p>Each field's value will be updated with the overridden bean instance.
*/
protected void injectFields(TestContext testContext) {
postProcessFields(testContext, (testMetadata, overrideRegistrar) -> overrideRegistrar.inject(
@ -64,9 +62,10 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
}
/**
* Process the test instance and make sure that flagged fields for bean
* overriding are processed. If a fresh instance is required, the field
* is nulled out and then re-injected with the overridden bean instance.
* Process the test instance and make sure that fields flagged for bean
* overriding are processed.
* <p>If a fresh instance is required, the field is nulled out and then
* re-injected with the overridden bean instance.
* <p>This method does nothing if the
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE}
* attribute is not present in the {@code TestContext}.

View File

@ -26,15 +26,15 @@ import org.springframework.core.style.ToStringCreator;
import org.springframework.lang.Nullable;
/**
* Metadata for Bean Override injection points, also responsible for the
* creation of the overriding instance.
* Metadata for Bean Override injection points, also responsible for creation of
* the overriding instance.
*
* <p><strong>WARNING</strong>: implementations are used as a cache key and
* must implement proper {@code equals} and {@code hashCode}t methods.
* must implement proper {@code equals()} and {@code hashCode()} methods.
*
* <p>Specific implementations of metadata can have state to be used during
* override {@linkplain #createOverride(String, BeanDefinition, Object)
* instance creation} &mdash; for example, from further parsing of the
* instance creation} &mdash; for example, based on further parsing of the
* annotation or the annotated field.
*
* @author Simon Baslé
@ -58,31 +58,32 @@ public abstract class OverrideMetadata {
}
/**
* Return the bean name to override.
* Get the bean name to override.
* <p>Defaults to the name of the {@link #getField() field}.
*/
protected String getBeanName() {
return this.field.getName();
}
/**
* Return the bean {@link ResolvableType type} to override.
* Get the bean {@linkplain ResolvableType type} to override.
*/
public ResolvableType getBeanType() {
public final ResolvableType getBeanType() {
return this.beanType;
}
/**
* Return the annotated {@link Field}.
* Get the annotated {@link Field}.
*/
public Field getField() {
public final Field getField() {
return this.field;
}
/**
* Return the {@link BeanOverrideStrategy} for this instance, as a hint on
* Get the {@link BeanOverrideStrategy} for this instance, as a hint on
* how and when the override instance should be created.
*/
public BeanOverrideStrategy getStrategy() {
public final BeanOverrideStrategy getStrategy() {
return this.strategy;
}
@ -91,9 +92,9 @@ public abstract class OverrideMetadata {
* optionally provided with an existing {@link BeanDefinition} and/or an
* original instance, that is a singleton or an early wrapped instance.
* @param beanName the name of the bean being overridden
* @param existingBeanDefinition an existing bean definition for that bean
* name, or {@code null} if not relevant
* @param existingBeanInstance an existing instance for that bean name,
* @param existingBeanDefinition an existing bean definition for the supplied
* bean name, or {@code null} if not relevant
* @param existingBeanInstance an existing instance for the supplied bean name
* for wrapping purposes, or {@code null} if irrelevant
* @return the instance with which to override the bean
*/