spring ConstructorOrFactoryMethodResolver 源码
spring ConstructorOrFactoryMethodResolver 代码
文件路径:/spring-beans/src/main/java/org/springframework/beans/factory/aot/ConstructorOrFactoryMethodResolver.java
/*
 * Copyright 2002-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.beans.factory.aot;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
 * Resolves the {@link Executable} (factory method or constructor) that should
 * be used to create a bean. This class is similar to
 * {@code org.springframework.beans.factory.support.ConstructorResolver} but it
 * doesn't need bean initialization.
 *
 * @author Stephane Nicoll
 * @author Phillip Webb
 * @since 6.0
 */
class ConstructorOrFactoryMethodResolver {
	private final ConfigurableBeanFactory beanFactory;
	@Nullable
	private final ClassLoader classLoader;
	ConstructorOrFactoryMethodResolver(ConfigurableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		this.classLoader = (beanFactory.getBeanClassLoader() != null ?
				beanFactory.getBeanClassLoader() : ClassUtils.getDefaultClassLoader());
	}
	@Nullable
	Executable resolve(BeanDefinition beanDefinition) {
		Supplier<ResolvableType> beanType = () -> getBeanType(beanDefinition);
		List<ResolvableType> valueTypes = (beanDefinition.hasConstructorArgumentValues() ?
				determineParameterValueTypes(beanDefinition.getConstructorArgumentValues()) :
				Collections.emptyList());
		Method resolvedFactoryMethod = resolveFactoryMethod(beanDefinition, valueTypes);
		if (resolvedFactoryMethod != null) {
			return resolvedFactoryMethod;
		}
		Class<?> factoryBeanClass = getFactoryBeanClass(beanDefinition);
		if (factoryBeanClass != null && !factoryBeanClass.equals(beanDefinition.getResolvableType().toClass())) {
			ResolvableType resolvableType = beanDefinition.getResolvableType();
			boolean isCompatible = ResolvableType.forClass(factoryBeanClass)
					.as(FactoryBean.class).getGeneric(0).isAssignableFrom(resolvableType);
			Assert.state(isCompatible, () -> String.format(
					"Incompatible target type '%s' for factory bean '%s'",
					resolvableType.toClass().getName(), factoryBeanClass.getName()));
			return resolveConstructor(() -> ResolvableType.forClass(factoryBeanClass), valueTypes);
		}
		Executable resolvedConstructor = resolveConstructor(beanType, valueTypes);
		if (resolvedConstructor != null) {
			return resolvedConstructor;
		}
		Field field = ReflectionUtils.findField(RootBeanDefinition.class, "resolvedConstructorOrFactoryMethod");
		if (field != null) {
			ReflectionUtils.makeAccessible(field);
			return (Executable) ReflectionUtils.getField(field, beanDefinition);
		}
		return null;
	}
	private List<ResolvableType> determineParameterValueTypes(
			ConstructorArgumentValues constructorArgumentValues) {
		List<ResolvableType> parameterTypes = new ArrayList<>();
		for (ValueHolder valueHolder : constructorArgumentValues
				.getIndexedArgumentValues().values()) {
			parameterTypes.add(determineParameterValueType(valueHolder));
		}
		return parameterTypes;
	}
	private ResolvableType determineParameterValueType(ValueHolder valueHolder) {
		if (valueHolder.getType() != null) {
			return ResolvableType.forClass(loadClass(valueHolder.getType()));
		}
		Object value = valueHolder.getValue();
		if (value instanceof BeanReference br) {
			if (value instanceof RuntimeBeanReference rbr) {
				if (rbr.getBeanType() != null) {
					return ResolvableType.forClass(rbr.getBeanType());
				}
			}
			return ResolvableType.forClass(this.beanFactory.getType(br.getBeanName(), false));
		}
		if (value instanceof BeanDefinition bd) {
			return extractTypeFromBeanDefinition(getBeanType(bd));
		}
		if (value instanceof Class<?> clazz) {
			return ResolvableType.forClassWithGenerics(Class.class, clazz);
		}
		return ResolvableType.forInstance(value);
	}
	private ResolvableType extractTypeFromBeanDefinition(ResolvableType type) {
		if (FactoryBean.class.isAssignableFrom(type.toClass())) {
			return type.as(FactoryBean.class).getGeneric(0);
		}
		return type;
	}
	@Nullable
	private Method resolveFactoryMethod(BeanDefinition beanDefinition, List<ResolvableType> valueTypes) {
		if (beanDefinition instanceof RootBeanDefinition rbd) {
			Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod();
			if (resolvedFactoryMethod != null) {
				return resolvedFactoryMethod;
			}
		}
		String factoryMethodName = beanDefinition.getFactoryMethodName();
		if (factoryMethodName != null) {
			String factoryBeanName = beanDefinition.getFactoryBeanName();
			Class<?> beanClass = getBeanClass(factoryBeanName != null ?
					this.beanFactory.getMergedBeanDefinition(factoryBeanName) : beanDefinition);
			List<Method> methods = new ArrayList<>();
			Assert.state(beanClass != null,
					() -> "Failed to determine bean class of " + beanDefinition);
			ReflectionUtils.doWithMethods(beanClass, methods::add,
					method -> isFactoryMethodCandidate(beanClass, method, factoryMethodName));
			if (methods.size() >= 1) {
				Function<Method, List<ResolvableType>> parameterTypesFactory = method -> {
					List<ResolvableType> types = new ArrayList<>();
					for (int i = 0; i < method.getParameterCount(); i++) {
						types.add(ResolvableType.forMethodParameter(method, i));
					}
					return types;
				};
				return (Method) resolveFactoryMethod(methods, parameterTypesFactory, valueTypes);
			}
		}
		return null;
	}
	private boolean isFactoryMethodCandidate(Class<?> beanClass, Method method, String factoryMethodName) {
		if (method.getName().equals(factoryMethodName)) {
			if (Modifier.isStatic(method.getModifiers())) {
				return method.getDeclaringClass().equals(beanClass);
			}
			return !Modifier.isPrivate(method.getModifiers());
		}
		return false;
	}
	@Nullable
	private Executable resolveConstructor(Supplier<ResolvableType> beanType, List<ResolvableType> valueTypes) {
		Class<?> type = ClassUtils.getUserClass(beanType.get().toClass());
		Constructor<?>[] constructors = type.getDeclaredConstructors();
		if (constructors.length == 1) {
			return constructors[0];
		}
		for (Constructor<?> constructor : constructors) {
			if (MergedAnnotations.from(constructor).isPresent(Autowired.class)) {
				return constructor;
			}
		}
		Function<Constructor<?>, List<ResolvableType>> parameterTypesFactory = executable -> {
			List<ResolvableType> types = new ArrayList<>();
			for (int i = 0; i < executable.getParameterCount(); i++) {
				types.add(ResolvableType.forConstructorParameter(executable, i));
			}
			return types;
		};
		List<? extends Executable> matches = Arrays.stream(constructors)
				.filter(executable -> match(parameterTypesFactory.apply(executable),
						valueTypes, FallbackMode.NONE))
				.toList();
		if (matches.size() == 1) {
			return matches.get(0);
		}
		List<? extends Executable> assignableElementFallbackMatches = Arrays
				.stream(constructors)
				.filter(executable -> match(parameterTypesFactory.apply(executable),
						valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
				.toList();
		if (assignableElementFallbackMatches.size() == 1) {
			return assignableElementFallbackMatches.get(0);
		}
		List<? extends Executable> typeConversionFallbackMatches = Arrays
				.stream(constructors)
				.filter(executable -> match(parameterTypesFactory.apply(executable),
						valueTypes, FallbackMode.TYPE_CONVERSION))
				.toList();
		return (typeConversionFallbackMatches.size() == 1)
				? typeConversionFallbackMatches.get(0) : null;
	}
	@Nullable
	private Executable resolveFactoryMethod(List<Method> executables,
			Function<Method, List<ResolvableType>> parameterTypesFactory,
			List<ResolvableType> valueTypes) {
		List<? extends Executable> matches = executables.stream()
				.filter(executable -> match(parameterTypesFactory.apply(executable), valueTypes, FallbackMode.NONE))
				.toList();
		if (matches.size() == 1) {
			return matches.get(0);
		}
		List<? extends Executable> assignableElementFallbackMatches = executables.stream()
				.filter(executable -> match(parameterTypesFactory.apply(executable),
						valueTypes, FallbackMode.ASSIGNABLE_ELEMENT))
				.toList();
		if (assignableElementFallbackMatches.size() == 1) {
			return assignableElementFallbackMatches.get(0);
		}
		List<? extends Executable> typeConversionFallbackMatches = executables.stream()
				.filter(executable -> match(parameterTypesFactory.apply(executable),
						valueTypes, FallbackMode.TYPE_CONVERSION))
				.toList();
		Assert.state(typeConversionFallbackMatches.size() <= 1,
				() -> "Multiple matches with parameters '" + valueTypes + "': " + typeConversionFallbackMatches);
		return (typeConversionFallbackMatches.size() == 1 ? typeConversionFallbackMatches.get(0) : null);
	}
	private boolean match(
			List<ResolvableType> parameterTypes, List<ResolvableType> valueTypes, FallbackMode fallbackMode) {
		if (parameterTypes.size() != valueTypes.size()) {
			return false;
		}
		for (int i = 0; i < parameterTypes.size(); i++) {
			if (!isMatch(parameterTypes.get(i), valueTypes.get(i), fallbackMode)) {
				return false;
			}
		}
		return true;
	}
	private boolean isMatch(ResolvableType parameterType, ResolvableType valueType, FallbackMode fallbackMode) {
		if (isAssignable(valueType).test(parameterType)) {
			return true;
		}
		return switch (fallbackMode) {
			case ASSIGNABLE_ELEMENT ->
					isAssignable(valueType).test(extractElementType(parameterType));
			case TYPE_CONVERSION -> typeConversionFallback(valueType).test(parameterType);
			default -> false;
		};
	}
	private Predicate<ResolvableType> isAssignable(ResolvableType valueType) {
		return parameterType -> parameterType.isAssignableFrom(valueType);
	}
	private ResolvableType extractElementType(ResolvableType parameterType) {
		if (parameterType.isArray()) {
			return parameterType.getComponentType();
		}
		if (Collection.class.isAssignableFrom(parameterType.toClass())) {
			return parameterType.as(Collection.class).getGeneric(0);
		}
		return ResolvableType.NONE;
	}
	private Predicate<ResolvableType> typeConversionFallback(ResolvableType valueType) {
		return parameterType -> {
			if (valueOrCollection(valueType, this::isStringForClassFallback).test(parameterType)) {
				return true;
			}
			return valueOrCollection(valueType, this::isSimpleValueType).test(parameterType);
		};
	}
	private Predicate<ResolvableType> valueOrCollection(ResolvableType valueType,
			Function<ResolvableType, Predicate<ResolvableType>> predicateProvider) {
		return parameterType -> {
			if (predicateProvider.apply(valueType).test(parameterType)) {
				return true;
			}
			if (predicateProvider.apply(extractElementType(valueType)).test(extractElementType(parameterType))) {
				return true;
			}
			return (predicateProvider.apply(valueType).test(extractElementType(parameterType)));
		};
	}
	/**
	 * Return a {@link Predicate} for a parameter type that checks if its target
	 * value is a {@link Class} and the value type is a {@link String}. This is
	 * a regular use cases where a {@link Class} is defined in the bean
	 * definition as an FQN.
	 * @param valueType the type of the value
	 * @return a predicate to indicate a fallback match for a String to Class
	 * parameter
	 */
	private Predicate<ResolvableType> isStringForClassFallback(ResolvableType valueType) {
		return parameterType -> (valueType.isAssignableFrom(String.class) &&
				parameterType.isAssignableFrom(Class.class));
	}
	private Predicate<ResolvableType> isSimpleValueType(ResolvableType valueType) {
		return parameterType -> (BeanUtils.isSimpleValueType(parameterType.toClass()) &&
				BeanUtils.isSimpleValueType(valueType.toClass()));
	}
	@Nullable
	private Class<?> getFactoryBeanClass(BeanDefinition beanDefinition) {
		if (beanDefinition instanceof RootBeanDefinition rbd) {
			if (rbd.hasBeanClass()) {
				Class<?> beanClass = rbd.getBeanClass();
				return (FactoryBean.class.isAssignableFrom(beanClass) ? beanClass : null);
			}
		}
		return null;
	}
	@Nullable
	private Class<?> getBeanClass(BeanDefinition beanDefinition) {
		if (beanDefinition instanceof AbstractBeanDefinition abd && abd.hasBeanClass()) {
			return abd.getBeanClass();
		}
		return (beanDefinition.getBeanClassName() != null ? loadClass(beanDefinition.getBeanClassName()) : null);
	}
	private ResolvableType getBeanType(BeanDefinition beanDefinition) {
		ResolvableType resolvableType = beanDefinition.getResolvableType();
		if (resolvableType != ResolvableType.NONE) {
			return resolvableType;
		}
		if (beanDefinition instanceof RootBeanDefinition rbd) {
			if (rbd.hasBeanClass()) {
				return ResolvableType.forClass(rbd.getBeanClass());
			}
		}
		String beanClassName = beanDefinition.getBeanClassName();
		if (beanClassName != null) {
			return ResolvableType.forClass(loadClass(beanClassName));
		}
		throw new IllegalStateException(
				"Failed to determine bean class of " + beanDefinition);
	}
	private Class<?> loadClass(String beanClassName) {
		try {
			return ClassUtils.forName(beanClassName, this.classLoader);
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException("Failed to load class " + beanClassName);
		}
	}
	@Nullable
	static Executable resolve(RegisteredBean registeredBean) {
		return new ConstructorOrFactoryMethodResolver(registeredBean.getBeanFactory())
				.resolve(registeredBean.getMergedBeanDefinition());
	}
	enum FallbackMode {
		NONE,
		ASSIGNABLE_ELEMENT,
		TYPE_CONVERSION
	}
}
相关信息
相关文章
spring AutowiredArgumentsCodeGenerator 源码
spring AutowiredElementResolver 源码
spring AutowiredFieldValueResolver 源码
spring AutowiredMethodArgumentsResolver 源码
spring BeanDefinitionMethodGenerator 源码
spring BeanDefinitionMethodGeneratorFactory 源码
                        
                            0
                        
                        
                             赞
                        
                    
                    
                热门推荐
- 
                        2、 - 优质文章
- 
                        3、 gate.io
- 
                        8、 openharmony
- 
                        9、 golang