001/* 002 * Copyright 2002-2020 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; 020import java.util.Properties; 021 022import org.springframework.beans.factory.BeanFactory; 023import org.springframework.beans.factory.BeanFactoryAware; 024import org.springframework.beans.factory.FactoryBean; 025import org.springframework.beans.factory.config.BeanDefinition; 026import org.springframework.beans.factory.config.BeanDefinitionHolder; 027import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 028import org.springframework.beans.factory.config.DependencyDescriptor; 029import org.springframework.core.ResolvableType; 030import org.springframework.lang.Nullable; 031import org.springframework.util.ClassUtils; 032 033/** 034 * Basic {@link AutowireCandidateResolver} that performs a full generic type 035 * match with the candidate's type if the dependency is declared as a generic type 036 * (e.g. Repository<Customer>). 037 * 038 * <p>This is the base class for 039 * {@link org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver}, 040 * providing an implementation all non-annotation-based resolution steps at this level. 041 * 042 * @author Juergen Hoeller 043 * @since 4.0 044 */ 045public class GenericTypeAwareAutowireCandidateResolver extends SimpleAutowireCandidateResolver 046 implements BeanFactoryAware, Cloneable { 047 048 @Nullable 049 private BeanFactory beanFactory; 050 051 052 @Override 053 public void setBeanFactory(BeanFactory beanFactory) { 054 this.beanFactory = beanFactory; 055 } 056 057 @Nullable 058 protected final BeanFactory getBeanFactory() { 059 return this.beanFactory; 060 } 061 062 063 @Override 064 public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { 065 if (!super.isAutowireCandidate(bdHolder, descriptor)) { 066 // If explicitly false, do not proceed with any other checks... 067 return false; 068 } 069 return checkGenericTypeMatch(bdHolder, descriptor); 070 } 071 072 /** 073 * Match the given dependency type with its generic type information against the given 074 * candidate bean definition. 075 */ 076 protected boolean checkGenericTypeMatch(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { 077 ResolvableType dependencyType = descriptor.getResolvableType(); 078 if (dependencyType.getType() instanceof Class) { 079 // No generic type -> we know it's a Class type-match, so no need to check again. 080 return true; 081 } 082 083 ResolvableType targetType = null; 084 boolean cacheType = false; 085 RootBeanDefinition rbd = null; 086 if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) { 087 rbd = (RootBeanDefinition) bdHolder.getBeanDefinition(); 088 } 089 if (rbd != null) { 090 targetType = rbd.targetType; 091 if (targetType == null) { 092 cacheType = true; 093 // First, check factory method return type, if applicable 094 targetType = getReturnTypeForFactoryMethod(rbd, descriptor); 095 if (targetType == null) { 096 RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd); 097 if (dbd != null) { 098 targetType = dbd.targetType; 099 if (targetType == null) { 100 targetType = getReturnTypeForFactoryMethod(dbd, descriptor); 101 } 102 } 103 } 104 } 105 } 106 107 if (targetType == null) { 108 // Regular case: straight bean instance, with BeanFactory available. 109 if (this.beanFactory != null) { 110 Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName()); 111 if (beanType != null) { 112 targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanType)); 113 } 114 } 115 // Fallback: no BeanFactory set, or no type resolvable through it 116 // -> best-effort match against the target class if applicable. 117 if (targetType == null && rbd != null && rbd.hasBeanClass() && rbd.getFactoryMethodName() == null) { 118 Class<?> beanClass = rbd.getBeanClass(); 119 if (!FactoryBean.class.isAssignableFrom(beanClass)) { 120 targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanClass)); 121 } 122 } 123 } 124 125 if (targetType == null) { 126 return true; 127 } 128 if (cacheType) { 129 rbd.targetType = targetType; 130 } 131 if (descriptor.fallbackMatchAllowed() && 132 (targetType.hasUnresolvableGenerics() || targetType.resolve() == Properties.class)) { 133 // Fallback matches allow unresolvable generics, e.g. plain HashMap to Map<String,String>; 134 // and pragmatically also java.util.Properties to any Map (since despite formally being a 135 // Map<Object,Object>, java.util.Properties is usually perceived as a Map<String,String>). 136 return true; 137 } 138 // Full check for complex generic type match... 139 return dependencyType.isAssignableFrom(targetType); 140 } 141 142 @Nullable 143 protected RootBeanDefinition getResolvedDecoratedDefinition(RootBeanDefinition rbd) { 144 BeanDefinitionHolder decDef = rbd.getDecoratedDefinition(); 145 if (decDef != null && this.beanFactory instanceof ConfigurableListableBeanFactory) { 146 ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory) this.beanFactory; 147 if (clbf.containsBeanDefinition(decDef.getBeanName())) { 148 BeanDefinition dbd = clbf.getMergedBeanDefinition(decDef.getBeanName()); 149 if (dbd instanceof RootBeanDefinition) { 150 return (RootBeanDefinition) dbd; 151 } 152 } 153 } 154 return null; 155 } 156 157 @Nullable 158 protected ResolvableType getReturnTypeForFactoryMethod(RootBeanDefinition rbd, DependencyDescriptor descriptor) { 159 // Should typically be set for any kind of factory method, since the BeanFactory 160 // pre-resolves them before reaching out to the AutowireCandidateResolver... 161 ResolvableType returnType = rbd.factoryMethodReturnType; 162 if (returnType == null) { 163 Method factoryMethod = rbd.getResolvedFactoryMethod(); 164 if (factoryMethod != null) { 165 returnType = ResolvableType.forMethodReturnType(factoryMethod); 166 } 167 } 168 if (returnType != null) { 169 Class<?> resolvedClass = returnType.resolve(); 170 if (resolvedClass != null && descriptor.getDependencyType().isAssignableFrom(resolvedClass)) { 171 // Only use factory method metadata if the return type is actually expressive enough 172 // for our dependency. Otherwise, the returned instance type may have matched instead 173 // in case of a singleton instance having been registered with the container already. 174 return returnType; 175 } 176 } 177 return null; 178 } 179 180 181 /** 182 * This implementation clones all instance fields through standard 183 * {@link Cloneable} support, allowing for subsequent reconfiguration 184 * of the cloned instance through a fresh {@link #setBeanFactory} call. 185 * @see #clone() 186 */ 187 @Override 188 public AutowireCandidateResolver cloneIfNecessary() { 189 try { 190 return (AutowireCandidateResolver) clone(); 191 } 192 catch (CloneNotSupportedException ex) { 193 throw new IllegalStateException(ex); 194 } 195 } 196 197}