|
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;
|
@@ -1043,7 +1044,7 @@ public Object doResolveDependency(DependencyDescriptor descriptor, String beanNa
|
1043 | 1044 | Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
|
1044 | 1045 | if (matchingBeans.isEmpty()) {
|
1045 | 1046 | if (descriptor.isRequired()) {
|
1046 |
| - raiseNoSuchBeanDefinitionException(type, descriptor.getResolvableType().toString(), descriptor); |
| 1047 | + raiseNoMatchingBeanFound(type, descriptor.getResolvableType().toString(), descriptor); |
1047 | 1048 | }
|
1048 | 1049 | return null;
|
1049 | 1050 | }
|
@@ -1382,17 +1383,46 @@ private boolean isSelfReference(String beanName, String candidateName) {
|
1382 | 1383 | }
|
1383 | 1384 |
|
1384 | 1385 | /**
|
1385 |
| - * Raise a NoSuchBeanDefinitionException for an unresolvable dependency. |
| 1386 | + * Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException |
| 1387 | + * for an unresolvable dependency. |
1386 | 1388 | */
|
1387 |
| - private void raiseNoSuchBeanDefinitionException( |
1388 |
| - Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) |
1389 |
| - throws NoSuchBeanDefinitionException { |
| 1389 | + private void raiseNoMatchingBeanFound( |
| 1390 | + Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) throws BeansException { |
| 1391 | + |
| 1392 | + checkBeanNotOfRequiredType(type, descriptor); |
1390 | 1393 |
|
1391 | 1394 | throw new NoSuchBeanDefinitionException(type, dependencyDescription,
|
1392 | 1395 | "expected at least 1 bean which qualifies as autowire candidate for this dependency. " +
|
1393 | 1396 | "Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
|
1394 | 1397 | }
|
1395 | 1398 |
|
| 1399 | + /** |
| 1400 | + * Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable, |
| 1401 | + * i.e. if the target type of the bean would match but an exposed proxy doesn't. |
| 1402 | + */ |
| 1403 | + private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) { |
| 1404 | + for (String beanName : this.beanDefinitionNames) { |
| 1405 | + RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); |
| 1406 | + Class<?> targetType = mbd.getTargetType(); |
| 1407 | + if (targetType != null && type.isAssignableFrom(targetType) && |
| 1408 | + isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) { |
| 1409 | + // Probably a poxy interfering with target type match -> throw meaningful exception. |
| 1410 | + Object beanInstance = getSingleton(beanName, false); |
| 1411 | + Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd)); |
| 1412 | + if (type != beanType) { |
| 1413 | + throw new BeanNotOfRequiredTypeException(beanName, type, beanType); |
| 1414 | + } |
| 1415 | + } |
| 1416 | + } |
| 1417 | + |
| 1418 | + if (getParentBeanFactory() instanceof DefaultListableBeanFactory) { |
| 1419 | + ((DefaultListableBeanFactory) getParentBeanFactory()).checkBeanNotOfRequiredType(type, descriptor); |
| 1420 | + } |
| 1421 | + } |
| 1422 | + |
| 1423 | + /** |
| 1424 | + * Create an {@link Optional} wrapper for the specified dependency. |
| 1425 | + */ |
1396 | 1426 | private Optional<?> createOptionalDependency(DependencyDescriptor descriptor, String beanName, final Object... args) {
|
1397 | 1427 | DependencyDescriptor descriptorToUse = new DependencyDescriptor(descriptor) {
|
1398 | 1428 | @Override
|
|
0 commit comments