Improve exception handling in bean override support
- Do not silently abort bean override processing if the ApplicationContext is not a BeanDefinitionRegistry. - Include conflicting bean names in error messages instead of just the number of conflicting beans. - Consistently throw IllegalStateException. - etc.
This commit is contained in:
@@ -130,15 +130,16 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
String beanName = overrideMetadata.getBeanName();
|
||||
BeanDefinition existingBeanDefinition = null;
|
||||
if (beanName == null) {
|
||||
Set<String> candidates = getExistingBeanNamesByType(beanFactory, overrideMetadata, true);
|
||||
if (candidates.size() != 1) {
|
||||
Field f = overrideMetadata.getField();
|
||||
throw new IllegalStateException("Unable to select a bean definition to override: " +
|
||||
candidates.size() + " bean definitions found of type " + overrideMetadata.getBeanType() +
|
||||
" (as required by annotated field '" + f.getDeclaringClass().getSimpleName() +
|
||||
"." + f.getName() + "')");
|
||||
Set<String> candidateNames = getExistingBeanNamesByType(beanFactory, overrideMetadata, true);
|
||||
int candidateCount = candidateNames.size();
|
||||
if (candidateCount != 1) {
|
||||
Field field = overrideMetadata.getField();
|
||||
throw new IllegalStateException("Unable to select a bean definition to override: found " +
|
||||
candidateCount + " bean definitions of type " + overrideMetadata.getBeanType() +
|
||||
" (as required by annotated field '" + field.getDeclaringClass().getSimpleName() +
|
||||
"." + field.getName() + "')" + (candidateCount > 0 ? ": " + candidateNames : ""));
|
||||
}
|
||||
beanName = candidates.iterator().next();
|
||||
beanName = candidateNames.iterator().next();
|
||||
existingBeanDefinition = beanFactory.getBeanDefinition(beanName);
|
||||
}
|
||||
else {
|
||||
@@ -147,8 +148,8 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
existingBeanDefinition = beanFactory.getBeanDefinition(beanName);
|
||||
}
|
||||
else if (enforceExistingDefinition) {
|
||||
throw new IllegalStateException("Unable to override bean '" + beanName + "': there is no" +
|
||||
" bean definition to replace with that name of type " + overrideMetadata.getBeanType());
|
||||
throw new IllegalStateException("Unable to override bean '" + beanName + "': there is no " +
|
||||
"bean definition to replace with that name of type " + overrideMetadata.getBeanType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,20 +182,21 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
String beanName = metadata.getBeanName();
|
||||
if (beanName == null) {
|
||||
Set<String> candidateNames = getExistingBeanNamesByType(beanFactory, metadata, true);
|
||||
if (candidateNames.size() != 1) {
|
||||
Field f = metadata.getField();
|
||||
throw new IllegalStateException("Unable to select a bean to override by wrapping: " +
|
||||
candidateNames.size() + " bean instances found of type " + metadata.getBeanType() +
|
||||
" (as required by annotated field '" + f.getDeclaringClass().getSimpleName() +
|
||||
"." + f.getName() + "')");
|
||||
int candidateCount = candidateNames.size();
|
||||
if (candidateCount != 1) {
|
||||
Field field = metadata.getField();
|
||||
throw new IllegalStateException("Unable to select a bean to override by wrapping: found " +
|
||||
candidateCount + " bean instances of type " + metadata.getBeanType() +
|
||||
" (as required by annotated field '" + field.getDeclaringClass().getSimpleName() +
|
||||
"." + field.getName() + "')" + (candidateCount > 0 ? ": " + candidateNames : ""));
|
||||
}
|
||||
beanName = candidateNames.iterator().next();
|
||||
}
|
||||
else {
|
||||
Set<String> candidates = getExistingBeanNamesByType(beanFactory, metadata, false);
|
||||
if (!candidates.contains(beanName)) {
|
||||
throw new IllegalStateException("Unable to override bean '" + beanName + "' by wrapping: there is no" +
|
||||
" existing bean instance with that name of type " + metadata.getBeanType());
|
||||
throw new IllegalStateException("Unable to override bean '" + beanName + "' by wrapping: there is no " +
|
||||
"existing bean instance with that name of type " + metadata.getBeanType());
|
||||
}
|
||||
}
|
||||
this.overrideRegistrar.markWrapEarly(metadata, beanName);
|
||||
|
||||
@@ -81,9 +81,11 @@ class BeanOverrideContextCustomizer implements ContextCustomizer {
|
||||
|
||||
@Override
|
||||
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
if (context instanceof BeanDefinitionRegistry registry) {
|
||||
registerInfrastructure(registry, this.detectedClasses);
|
||||
if (!(context instanceof BeanDefinitionRegistry registry)) {
|
||||
throw new IllegalStateException("Cannot process bean overrides with an ApplicationContext " +
|
||||
"that doesn't implement BeanDefinitionRegistry: " + context.getClass());
|
||||
}
|
||||
registerInfrastructure(registry, this.detectedClasses);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -111,9 +111,8 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
|
||||
@Override
|
||||
public TestBeanOverrideMetadata createMetadata(Annotation overrideAnnotation, Class<?> testClass, Field field) {
|
||||
if (!(overrideAnnotation instanceof TestBean testBeanAnnotation)) {
|
||||
throw new IllegalStateException(String.format("Invalid annotation passed to %s: expected @TestBean on field %s.%s",
|
||||
TestBeanOverrideProcessor.class.getSimpleName(), field.getDeclaringClass().getName(),
|
||||
field.getName()));
|
||||
throw new IllegalStateException("Invalid annotation passed to %s: expected @TestBean on field %s.%s"
|
||||
.formatted(getClass().getSimpleName(), field.getDeclaringClass().getName(), field.getName()));
|
||||
}
|
||||
Method overrideMethod;
|
||||
String methodName = testBeanAnnotation.methodName();
|
||||
@@ -172,7 +171,7 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
|
||||
return this.overrideMethod.invoke(null);
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new IllegalArgumentException("Could not invoke bean overriding method " + this.overrideMethod.getName() +
|
||||
throw new IllegalStateException("Failed to invoke bean overriding method " + this.overrideMethod.getName() +
|
||||
"; a static method with no formal parameters is expected", ex);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user