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}