001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.factory.support; 018 019import java.lang.reflect.Method; 020 021import org.springframework.beans.factory.BeanFactory; 022import org.springframework.beans.factory.BeanFactoryAware; 023import org.springframework.beans.factory.FactoryBean; 024import org.springframework.beans.factory.config.BeanDefinition; 025import org.springframework.beans.factory.config.BeanDefinitionHolder; 026import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 027import org.springframework.beans.factory.config.DependencyDescriptor; 028import org.springframework.core.ResolvableType; 029import org.springframework.util.ClassUtils; 030 031/** 032 * Basic {@link AutowireCandidateResolver} that performs a full generic type 033 * match with the candidate's type if the dependency is declared as a generic type 034 * (e.g. Repository<Customer>). 035 * 036 * <p>This is the base class for 037 * {@link org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver}, 038 * providing an implementation all non-annotation-based resolution steps at this level. 039 * 040 * @author Juergen Hoeller 041 * @since 4.0 042 */ 043public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver 044 implements BeanFactoryAware { 045 046 private BeanFactory beanFactory; 047 048 049 @Override 050 public void setBeanFactory(BeanFactory beanFactory) { 051 this.beanFactory = beanFactory; 052 } 053 054 protected final BeanFactory getBeanFactory() { 055 return this.beanFactory; 056 } 057 058 059 @Override 060 public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { 061 if (!super.isAutowireCandidate(bdHolder, descriptor)) { 062 // If explicitly false, do not proceed with any other checks... 063 return false; 064 } 065 return (descriptor == null || checkGenericTypeMatch(bdHolder, descriptor)); 066 } 067 068 /** 069 * Match the given dependency type with its generic type information against the given 070 * candidate bean definition. 071 */ 072 protected boolean checkGenericTypeMatch(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { 073 ResolvableType dependencyType = descriptor.getResolvableType(); 074 if (dependencyType.getType() instanceof Class) { 075 // No generic type -> we know it's a Class type-match, so no need to check again. 076 return true; 077 } 078 079 ResolvableType targetType = null; 080 boolean cacheType = false; 081 RootBeanDefinition rbd = null; 082 if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) { 083 rbd = (RootBeanDefinition) bdHolder.getBeanDefinition(); 084 } 085 if (rbd != null) { 086 targetType = rbd.targetType; 087 if (targetType == null) { 088 cacheType = true; 089 // First, check factory method return type, if applicable 090 targetType = getReturnTypeForFactoryMethod(rbd, descriptor); 091 if (targetType == null) { 092 RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd); 093 if (dbd != null) { 094 targetType = dbd.targetType; 095 if (targetType == null) { 096 targetType = getReturnTypeForFactoryMethod(dbd, descriptor); 097 } 098 } 099 } 100 } 101 } 102 103 if (targetType == null) { 104 // Regular case: straight bean instance, with BeanFactory available. 105 if (this.beanFactory != null) { 106 Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName()); 107 if (beanType != null) { 108 targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanType)); 109 } 110 } 111 // Fallback: no BeanFactory set, or no type resolvable through it 112 // -> best-effort match against the target class if applicable. 113 if (targetType == null && rbd != null && rbd.hasBeanClass() && rbd.getFactoryMethodName() == null) { 114 Class<?> beanClass = rbd.getBeanClass(); 115 if (!FactoryBean.class.isAssignableFrom(beanClass)) { 116 targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanClass)); 117 } 118 } 119 } 120 121 if (targetType == null) { 122 return true; 123 } 124 if (cacheType) { 125 rbd.targetType = targetType; 126 } 127 if (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics()) { 128 return true; 129 } 130 // Full check for complex generic type match... 131 return dependencyType.isAssignableFrom(targetType); 132 } 133 134 protected RootBeanDefinition getResolvedDecoratedDefinition(RootBeanDefinition rbd) { 135 BeanDefinitionHolder decDef = rbd.getDecoratedDefinition(); 136 if (decDef != null && this.beanFactory instanceof ConfigurableListableBeanFactory) { 137 ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory) this.beanFactory; 138 if (clbf.containsBeanDefinition(decDef.getBeanName())) { 139 BeanDefinition dbd = clbf.getMergedBeanDefinition(decDef.getBeanName()); 140 if (dbd instanceof RootBeanDefinition) { 141 return (RootBeanDefinition) dbd; 142 } 143 } 144 } 145 return null; 146 } 147 148 protected ResolvableType getReturnTypeForFactoryMethod(RootBeanDefinition rbd, DependencyDescriptor descriptor) { 149 // Should typically be set for any kind of factory method, since the BeanFactory 150 // pre-resolves them before reaching out to the AutowireCandidateResolver... 151 ResolvableType returnType = rbd.factoryMethodReturnType; 152 if (returnType == null) { 153 Method factoryMethod = rbd.getResolvedFactoryMethod(); 154 if (factoryMethod != null) { 155 returnType = ResolvableType.forMethodReturnType(factoryMethod); 156 } 157 } 158 if (returnType != null) { 159 Class<?> resolvedClass = returnType.resolve(); 160 if (resolvedClass != null && descriptor.getDependencyType().isAssignableFrom(resolvedClass)) { 161 // Only use factory method metadata if the return type is actually expressive enough 162 // for our dependency. Otherwise, the returned instance type may have matched instead 163 // in case of a singleton instance having been registered with the container already. 164 return returnType; 165 } 166 } 167 return null; 168 } 169 170}