|
52 | 52 | import org.springframework.beans.factory.BeanFactory; |
53 | 53 | import org.springframework.beans.factory.BeanFactoryAware; |
54 | 54 | import org.springframework.beans.factory.BeanFactoryUtils; |
| 55 | +import org.springframework.beans.factory.BeanNotOfRequiredTypeException; |
55 | 56 | import org.springframework.beans.factory.CannotLoadBeanClassException; |
56 | 57 | import org.springframework.beans.factory.FactoryBean; |
57 | 58 | import org.springframework.beans.factory.InjectionPoint; |
@@ -1053,7 +1054,7 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa |
1053 | 1054 | Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); |
1054 | 1055 | if (matchingBeans.isEmpty()) { |
1055 | 1056 | if (descriptor.isRequired()) { |
1056 | | - raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor); |
| 1057 | + raiseNoMatchingBeanFound(type, descriptor.getResolvableType().toString(), descriptor); |
1057 | 1058 | } |
1058 | 1059 | return null; |
1059 | 1060 | } |
@@ -1392,17 +1393,43 @@ private boolean isSelfReference(String beanName, String candidateName) { |
1392 | 1393 | } |
1393 | 1394 |
|
1394 | 1395 | /** |
1395 | | - * Raise a NoSuchBeanDefinitionException for an unresolvable dependency. |
| 1396 | + * Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException |
| 1397 | + * for an unresolvable dependency. |
1396 | 1398 | */ |
1397 | | - private void raiseNoSuchBeanDefinitionException( |
1398 | | - Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) |
1399 | | - throws NoSuchBeanDefinitionException { |
| 1399 | + private void raiseNoMatchingBeanFound( |
| 1400 | + Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) throws BeansException { |
| 1401 | + |
| 1402 | + checkBeanNotOfRequiredType(type, descriptor); |
1400 | 1403 |
|
1401 | 1404 | throw new NoSuchBeanDefinitionException(type, dependencyDescription, |
1402 | 1405 | "expected at least 1 bean which qualifies as autowire candidate for this dependency. " + |
1403 | 1406 | "Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations())); |
1404 | 1407 | } |
1405 | 1408 |
|
| 1409 | + /** |
| 1410 | + * Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable, |
| 1411 | + * i.e. if the target type of the bean would match but an exposed proxy doesn't. |
| 1412 | + */ |
| 1413 | + private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) { |
| 1414 | + for (String beanName : this.beanDefinitionNames) { |
| 1415 | + RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); |
| 1416 | + Class<?> targetType = mbd.getTargetType(); |
| 1417 | + if (targetType != null && type.isAssignableFrom(targetType) && |
| 1418 | + isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) { |
| 1419 | + // Probably a poxy interfering with target type match -> throw meaningful exception. |
| 1420 | + Object beanInstance = getSingleton(beanName, false); |
| 1421 | + Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd)); |
| 1422 | + if (type != beanType) { |
| 1423 | + throw new BeanNotOfRequiredTypeException(beanName, type, beanType); |
| 1424 | + } |
| 1425 | + } |
| 1426 | + } |
| 1427 | + |
| 1428 | + if (getParentBeanFactory() instanceof DefaultListableBeanFactory) { |
| 1429 | + ((DefaultListableBeanFactory) getParentBeanFactory()).checkBeanNotOfRequiredType(type, descriptor); |
| 1430 | + } |
| 1431 | + } |
| 1432 | + |
1406 | 1433 |
|
1407 | 1434 | @Override |
1408 | 1435 | public String toString() { |
|
0 commit comments