Improve @PropertyMapping error message
Improve the message thrown when a @PropertyMapping is used in combination with a @Component to include the actual annotations that are causing the problem. Fixes gh-5897
This commit is contained in:
parent
66b69f4346
commit
cd365bcae1
|
|
@ -16,6 +16,10 @@
|
|||
|
||||
package org.springframework.boot.test.autoconfigure.properties;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
|
@ -24,7 +28,7 @@ import org.springframework.core.env.Environment;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* {@link ContextCustomizer} to map annotation attributes to {@link Environment}
|
||||
|
|
@ -72,17 +76,49 @@ class PropertyMappingContextCustomizer implements ContextCustomizer {
|
|||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
Class<?> beanClass = bean.getClass();
|
||||
boolean hasComponent = AnnotationUtils.findAnnotation(beanClass,
|
||||
Component.class) != null;
|
||||
boolean hasPropertyMapping = AnnotationUtils.findAnnotation(beanClass,
|
||||
PropertyMapping.class) != null;
|
||||
if (hasComponent) {
|
||||
Assert.state(!hasPropertyMapping,
|
||||
"@PropertyMapping annotations can only be used on test classes");
|
||||
Set<Class<?>> components = new LinkedHashSet<Class<?>>();
|
||||
Set<Class<?>> propertyMappings = new LinkedHashSet<Class<?>>();
|
||||
while (beanClass != null) {
|
||||
for (Annotation annotation : AnnotationUtils.getAnnotations(beanClass)) {
|
||||
if (isAnnotated(annotation, Component.class)) {
|
||||
components.add(annotation.annotationType());
|
||||
}
|
||||
if (isAnnotated(annotation, PropertyMapping.class)) {
|
||||
propertyMappings.add(annotation.annotationType());
|
||||
}
|
||||
}
|
||||
beanClass = beanClass.getSuperclass();
|
||||
}
|
||||
if (!components.isEmpty() && !propertyMappings.isEmpty()) {
|
||||
throw new IllegalStateException("The @PropertyMapping "
|
||||
+ getAnnotationsDescription(propertyMappings)
|
||||
+ " cannot be used in combination with the @Component "
|
||||
+ getAnnotationsDescription(components));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private boolean isAnnotated(Annotation element,
|
||||
Class<? extends Annotation> annotationType) {
|
||||
try {
|
||||
return element.annotationType().equals(annotationType) || AnnotationUtils
|
||||
.findAnnotation(element.annotationType(), annotationType) != null;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getAnnotationsDescription(Set<Class<?>> annotations) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (Class<?> annotation : annotations) {
|
||||
result.append(result.length() == 0 ? "" : ", ");
|
||||
result.append("@" + ClassUtils.getShortName(annotation));
|
||||
}
|
||||
result.insert(0, annotations.size() == 1 ? "annotation " : "annotations ");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
|
|
|
|||
|
|
@ -107,8 +107,9 @@ public class PropertyMappingContextCustomizerFactoryTests {
|
|||
context.register(ConfigMapping.class);
|
||||
customizer.customizeContext(context, null);
|
||||
this.thrown.expect(BeanCreationException.class);
|
||||
this.thrown.expectMessage(
|
||||
"@PropertyMapping annotations can only be used on test classes");
|
||||
this.thrown.expectMessage("The @PropertyMapping annotation "
|
||||
+ "@PropertyMappingContextCustomizerFactoryTests.TypeMappingAnnotation "
|
||||
+ "cannot be used in combination with the @Component annotation @Configuration");
|
||||
context.refresh();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue