|
16 | 16 |
|
17 | 17 | package org.springframework.boot.test.autoconfigure.properties;
|
18 | 18 |
|
| 19 | +import java.lang.annotation.Annotation; |
| 20 | +import java.util.LinkedHashSet; |
| 21 | +import java.util.Set; |
| 22 | + |
19 | 23 | import org.springframework.beans.BeansException;
|
20 | 24 | import org.springframework.beans.factory.config.BeanPostProcessor;
|
21 | 25 | import org.springframework.context.ConfigurableApplicationContext;
|
|
24 | 28 | import org.springframework.stereotype.Component;
|
25 | 29 | import org.springframework.test.context.ContextCustomizer;
|
26 | 30 | import org.springframework.test.context.MergedContextConfiguration;
|
27 |
| -import org.springframework.util.Assert; |
| 31 | +import org.springframework.util.ClassUtils; |
28 | 32 |
|
29 | 33 | /**
|
30 | 34 | * {@link ContextCustomizer} to map annotation attributes to {@link Environment}
|
@@ -72,17 +76,49 @@ static class PropertyMappingCheckBeanPostProcessor implements BeanPostProcessor
|
72 | 76 | public Object postProcessBeforeInitialization(Object bean, String beanName)
|
73 | 77 | throws BeansException {
|
74 | 78 | Class<?> beanClass = bean.getClass();
|
75 |
| - boolean hasComponent = AnnotationUtils.findAnnotation(beanClass, |
76 |
| - Component.class) != null; |
77 |
| - boolean hasPropertyMapping = AnnotationUtils.findAnnotation(beanClass, |
78 |
| - PropertyMapping.class) != null; |
79 |
| - if (hasComponent) { |
80 |
| - Assert.state(!hasPropertyMapping, |
81 |
| - "@PropertyMapping annotations can only be used on test classes"); |
| 79 | + Set<Class<?>> components = new LinkedHashSet<Class<?>>(); |
| 80 | + Set<Class<?>> propertyMappings = new LinkedHashSet<Class<?>>(); |
| 81 | + while (beanClass != null) { |
| 82 | + for (Annotation annotation : AnnotationUtils.getAnnotations(beanClass)) { |
| 83 | + if (isAnnotated(annotation, Component.class)) { |
| 84 | + components.add(annotation.annotationType()); |
| 85 | + } |
| 86 | + if (isAnnotated(annotation, PropertyMapping.class)) { |
| 87 | + propertyMappings.add(annotation.annotationType()); |
| 88 | + } |
| 89 | + } |
| 90 | + beanClass = beanClass.getSuperclass(); |
| 91 | + } |
| 92 | + if (!components.isEmpty() && !propertyMappings.isEmpty()) { |
| 93 | + throw new IllegalStateException("The @PropertyMapping " |
| 94 | + + getAnnotationsDescription(propertyMappings) |
| 95 | + + " cannot be used in combination with the @Component " |
| 96 | + + getAnnotationsDescription(components)); |
82 | 97 | }
|
83 | 98 | return bean;
|
84 | 99 | }
|
85 | 100 |
|
| 101 | + private boolean isAnnotated(Annotation element, |
| 102 | + Class<? extends Annotation> annotationType) { |
| 103 | + try { |
| 104 | + return element.annotationType().equals(annotationType) || AnnotationUtils |
| 105 | + .findAnnotation(element.annotationType(), annotationType) != null; |
| 106 | + } |
| 107 | + catch (Throwable ex) { |
| 108 | + return false; |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + private String getAnnotationsDescription(Set<Class<?>> annotations) { |
| 113 | + StringBuilder result = new StringBuilder(); |
| 114 | + for (Class<?> annotation : annotations) { |
| 115 | + result.append(result.length() == 0 ? "" : ", "); |
| 116 | + result.append("@" + ClassUtils.getShortName(annotation)); |
| 117 | + } |
| 118 | + result.insert(0, annotations.size() == 1 ? "annotation " : "annotations "); |
| 119 | + return result.toString(); |
| 120 | + } |
| 121 | + |
86 | 122 | @Override
|
87 | 123 | public Object postProcessAfterInitialization(Object bean, String beanName)
|
88 | 124 | throws BeansException {
|
|
0 commit comments