package org.theonefx.wcframework.ioc; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.theonefx.wcframework.core.ClassWrapper; import org.theonefx.wcframework.core.TypeConverter; import org.theonefx.wcframework.core.exception.BeanCreationException; import org.theonefx.wcframework.core.exception.BeanDefinitionStoreException; import org.theonefx.wcframework.ioc.exception.TypeMismatchException; import org.theonefx.wcframework.ioc.exception.UnsatisfiedDependencyException; import org.theonefx.wcframework.ioc.val.ConstructorArgumentValues; import org.theonefx.wcframework.ioc.val.ConstructorArgumentValues.ValueHolder; import org.theonefx.wcframework.ioc.val.GenericTypeResolver; import org.theonefx.wcframework.ioc.val.MethodParameter; import org.theonefx.wcframework.utils.ClassUtils; import org.theonefx.wcframework.utils.ObjectUtils; import org.theonefx.wcframework.utils.ReflectionUtils; import org.theonefx.wcframework.utils.StringUtils; /** * Class的辅助类,用于解析构造函数和工厂方法。 * 根据给定的参数匹配构造函数。 */ class ConstructorResolver { private final AbstractBeanFactory beanFactory; /** * Create a new ConstructorResolver for the given factory and instantiation strategy. */ public ConstructorResolver(AbstractBeanFactory beanFactory) { this.beanFactory = beanFactory; } /** * "autowire constructor" (with constructor arguments by type) behavior. * Also applied if explicit constructor argument values are specified, * matching all remaining arguments with beans from the bean factory. * <p> * This corresponds to constructor injection: In this mode, a Spring bean * factory is able to host components that expect constructor-based * dependency resolution. * * @param id * the name of the bean * @param mbd * the merged bean definition for the bean * @param chosenCtors * chosen candidate constructors (or <code>null</code> if none) * @param explicitArgs * argument values passed in programmatically via the getBean * method, or <code>null</code> if none (-> use constructor * argument values from bean definition) * @return a BeanWrapper for the new instance */ public BeanWrapper autowireConstructor(final ClassWrapper<?> classWrapper, final String id, final RootBeanDefinition mbd) { BeanWrapperImpl bw = new BeanWrapperImpl(); Constructor<?> constructorToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod; if (constructorToUse != null && mbd.constructorArgumentsResolved) { // 找到一个缓存的构造函数 argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { argsToUse = resolvePreparedArguments(id, mbd, bw, constructorToUse, argsToResolve); } if (constructorToUse == null) { // 需要确定构造函数 ConstructorArgumentValues resolvedValues = null; int minNrOfArgs; ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(id, mbd, bw, cargs, resolvedValues); // Take specified constructors, if any. Constructor<?>[] candidates = null; Class<?> beanClass = mbd.getBeanClass(); try { candidates = beanClass.getConstructors(); } catch (Throwable ex) { throw new BeanCreationException(id, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex); } int minTypeDiffWeight = Integer.MAX_VALUE; Set<Constructor<?>> ambiguousConstructors = null; for (int i = 0; i < candidates.length; i++) { Constructor<?> candidate = candidates[i]; Class<?>[] paramTypes = candidate.getParameterTypes(); if (constructorToUse != null && argsToUse.length > paramTypes.length) { // Already found greedy constructor that can be satisfied -> // do not look any further, there are only less greedy // constructors left. break; } if (paramTypes.length < minNrOfArgs) { continue; } ArgumentsHolder argsHolder; argsHolder = createArgumentArray(id, mbd, resolvedValues, bw, paramTypes, candidate); int typeDiffWeight = argsHolder.getTypeDifferenceWeight(paramTypes); // Choose this constructor if it represents the closest match. if (typeDiffWeight < minTypeDiffWeight) { constructorToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousConstructors = null; } else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousConstructors == null) { ambiguousConstructors = new LinkedHashSet<Constructor<?>>(); ambiguousConstructors.add(constructorToUse); } ambiguousConstructors.add(candidate); } } if (constructorToUse == null) { throw new BeanCreationException(id, "无法找到符合条件的构造函数" + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); } argsHolderToUse.storeCache(mbd, constructorToUse); } try { Object beanInstance; if (System.getSecurityManager() != null) { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return beanFactory.getInstantiationStrategy().instantiate(classWrapper, mbd, id, beanFactory, ctorToUse, argumentsToUse); } }, beanFactory.getAccessControlContext()); } else { beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(classWrapper, mbd, id, this.beanFactory, constructorToUse, argsToUse); } bw.setWrappedInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(id, "Instantiation of bean failed", ex); } } /** * 使用确定名称的工厂方法创建Bean实例。 * 如果没有定义factory-bean属性但是却定义了factory-method以及class属性,那么代表着factory-method是class的一个static方法 * 否则的话肯定是使用BeanFactory中通过配置了依赖注入得来的对象的实例方法来生成目标对象。 * <p> * 实现过程需要遍历所有与RootBeanDefinition指定的名称相同的静态方法或实例方法。 */ public BeanWrapper instantiateUsingFactoryMethod(final ClassWrapper<?> classWrapper, final String id, final RootBeanDefinition mbd) { BeanWrapperImpl bw = new BeanWrapperImpl(); Object factoryBean; Class<?> factoryClass; boolean isStatic; String factoryBeanName = mbd.getFactoryBeanName(); if (factoryBeanName != null) { if (factoryBeanName.equals(id)) { throw new BeanDefinitionStoreException(id, "生成bean的工厂是自己,这是一个圈...."); } try { factoryBean = this.beanFactory.getBean(factoryBeanName); } catch (BeanCreationException e) { throw new BeanCreationException(id, "创建ID为 '" + factoryBeanName + "' 的工厂Bean时发生异常", e); } if (factoryBean == null) { throw new BeanCreationException(id, "ID 为 '" + factoryBeanName + "' 的工厂Bean不存在"); } factoryClass = factoryBean.getClass(); isStatic = false; } else { // 没有factoryBean定义,那么肯定是使用静态方法创建 if (!mbd.hasBeanClass()) { throw new BeanDefinitionStoreException(id, "bean定义中既没有说明是哪个类(使用其静态方法创建),也没有说明是哪个bean工厂(使用其对象方法创建)"); } factoryBean = null; factoryClass = mbd.getBeanClass(); isStatic = true; } Method factoryMethodToUse = null; ArgumentsHolder argsHolderToUse = null; Object[] argsToUse = null; Object[] argsToResolve = null; synchronized (mbd.constructorArgumentLock) { factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod; if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) { // Found a cached factory method... argsToUse = mbd.resolvedConstructorArguments; if (argsToUse == null) { argsToResolve = mbd.preparedConstructorArguments; } } } if (argsToResolve != null) { argsToUse = resolvePreparedArguments(id, mbd, bw, factoryMethodToUse, argsToResolve); } if (factoryMethodToUse == null || argsToUse == null) { // 寻找工厂方法 // 先找到工厂方法所在的类 factoryClass = ClassUtils.getUserClass(factoryClass); Method[] rawCandidates; final Class<?> factoryClazz = factoryClass; if (System.getSecurityManager() != null) { rawCandidates = AccessController.doPrivileged(new PrivilegedAction<Method[]>() { public Method[] run() { return ReflectionUtils.getAllDeclaredMethods(factoryClazz); } }); } else { rawCandidates = ReflectionUtils.getAllDeclaredMethods(factoryClazz); } // 找到所有可能的方法,有可能有多个 List<Method> candidateSet = new ArrayList<Method>(); for (Method candidate : rawCandidates) { if (Modifier.isStatic(candidate.getModifiers()) == isStatic && candidate.getName().equals(mbd.getFactoryMethodName())) { candidateSet.add(candidate); } } Method[] candidates = candidateSet.toArray(new Method[candidateSet.size()]); ConstructorArgumentValues resolvedValues = null; int minTypeDiffWeight = Integer.MAX_VALUE; Set<Method> ambiguousFactoryMethods = null; int minNrOfArgs; // 找到bean定义中的所有构造函数的参数(供工厂方法调用) ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues(); resolvedValues = new ConstructorArgumentValues(); minNrOfArgs = resolveConstructorArguments(id, mbd, bw, cargs, resolvedValues); List<Exception> causes = null; // 遍历所有可能的方法 for (int i = 0; i < candidates.length; i++) { Method candidate = candidates[i]; Class<?>[] paramTypes = candidate.getParameterTypes(); if (paramTypes.length >= minNrOfArgs) { ArgumentsHolder argsHolder; // Resolved constructor arguments: type conversion and/or autowiring necessary. try { argsHolder = createArgumentArray(id, mbd, resolvedValues, bw, paramTypes, candidate); } catch (UnsatisfiedDependencyException ex) { if (this.beanFactory.log.isTraceEnabled()) { this.beanFactory.log.trace("由于异常" + ex + "导致忽bean'" + id + "'的工厂方法 [" + candidate + "]'"); } if (i == candidates.length - 1 && argsHolderToUse == null) { throw ex; } else { // 暂时不管这个异常,尝试下一个可能的方法 if (causes == null) { causes = new LinkedList<Exception>(); } causes.add(ex); continue; } } int typeDiffWeight = argsHolder.getTypeDifferenceWeight(paramTypes); // 选择最匹配的方法 if (typeDiffWeight < minTypeDiffWeight) { factoryMethodToUse = candidate; argsHolderToUse = argsHolder; argsToUse = argsHolder.arguments; minTypeDiffWeight = typeDiffWeight; ambiguousFactoryMethods = null; } else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight) { if (ambiguousFactoryMethods == null) { ambiguousFactoryMethods = new LinkedHashSet<Method>(); ambiguousFactoryMethods.add(factoryMethodToUse); } ambiguousFactoryMethods.add(candidate); } } } if (factoryMethodToUse == null) { boolean hasArgs = (resolvedValues.getArgumentCount() > 0); String argDesc = ""; if (hasArgs) { List<String> argTypes = new ArrayList<String>(); for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) { String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName()); argTypes.add(argType); } argDesc = StringUtils.collectionToCommaDelimitedString(argTypes); } throw new BeanCreationException(id, "找不到合适的工厂方法: " + (mbd.getFactoryBeanName() != null ? "工厂Bean '" + mbd.getFactoryBeanName() + "'; " : "") + "工厂方法 '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " + "请检查该方法" + (hasArgs ? "以及对应的参数表 " : "") + "是否存在,同时该方法还应该是一个 " + (isStatic ? "静态方法" : "非静态方法") + "."); } else if (void.class.equals(factoryMethodToUse.getReturnType())) { throw new BeanCreationException(id, "无效的工厂方法'" + mbd.getFactoryMethodName() + "': 该方法没有返回值!!!"); } if (argsHolderToUse != null) { argsHolderToUse.storeCache(mbd, factoryMethodToUse); } } try { Object beanInstance; if (System.getSecurityManager() != null) { final Object fb = factoryBean; final Method factoryMethod = factoryMethodToUse; final Object[] args = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return beanFactory.getInstantiationStrategy().instantiate(classWrapper, mbd, id, beanFactory, fb, factoryMethod, args); } }, beanFactory.getAccessControlContext()); } else { beanInstance = beanFactory.getInstantiationStrategy().instantiate(classWrapper, mbd, id, beanFactory, factoryBean, factoryMethodToUse, argsToUse); } if (beanInstance == null) { return null; } bw.setWrappedInstance(beanInstance); return bw; } catch (Throwable ex) { throw new BeanCreationException(id, "实例化Bean失败", ex); } } /** * 解析Bean的构造函数的参数,并保存到resolvedValues对象中。 * Resolve the constructor arguments for this bean into the resolvedValues object. * * 这将导致查询其他的Bean。 * This may involve looking up other beans. * * 该方法同时也用于处理静态工厂方法 * This method is also used for handling invocations of static factory methods. */ private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) { TypeConverter converter = bw; BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); int minNrOfArgs = cargs.getArgumentCount(); for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) { int index = entry.getKey(); if (index < 0) { throw new BeanCreationException(beanName, "无效的构造函数参数索引: " + index); } if (index > minNrOfArgs) { minNrOfArgs = index + 1; } ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue(); if (valueHolder.isConverted()) { resolvedValues.addIndexedArgumentValue(index, valueHolder); } else { Object resolvedValue = valueResolver.resolveValueIfNecessary("构造函数的参数", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder); } } for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) { if (valueHolder.isConverted()) { resolvedValues.addGenericArgumentValue(valueHolder); } else { Object resolvedValue = valueResolver.resolveValueIfNecessary("构造函数的参数", valueHolder.getValue()); ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType()); resolvedValueHolder.setSource(valueHolder); resolvedValues.addGenericArgumentValue(resolvedValueHolder); } } return minNrOfArgs; } /** * Create an array of arguments to invoke a constructor or factory method, * given the resolved constructor argument values. */ private ArgumentsHolder createArgumentArray(String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues, BeanWrapper bw, Class<?>[] paramTypes, Object methodOrCtor) throws UnsatisfiedDependencyException { String methodType = (methodOrCtor instanceof Constructor ? "构造函数" : "工厂方法"); ArgumentsHolder args = new ArgumentsHolder(paramTypes.length); Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length); Set<String> autowiredBeanNames = new LinkedHashSet<String>(4); for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { Class<?> paramType = paramTypes[paramIndex]; // Try to find matching constructor argument value, either indexed // or generic. ConstructorArgumentValues.ValueHolder valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, usedValueHolders); // If we couldn't find a direct match and are not supposed to // autowire, // let's try the next generic, untyped argument value as fallback: // it could match after type conversion (for example, String -> // int). if (valueHolder == null) { valueHolder = resolvedValues.getGenericArgumentValue(null, usedValueHolders); } // We found a potential match - let's give it a try. // Do not consider the same value definition multiple times! usedValueHolders.add(valueHolder); Object originalValue = valueHolder.getValue(); Object convertedValue; if (valueHolder.isConverted()) { convertedValue = valueHolder.getConvertedValue(); args.preparedArguments[paramIndex] = convertedValue; } else { ConstructorArgumentValues.ValueHolder sourceHolder = (ConstructorArgumentValues.ValueHolder) valueHolder.getSource(); Object sourceValue = sourceHolder.getValue(); try { convertedValue = bw.convertIfNecessary(originalValue, paramType, MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex)); args.resolveNecessary = true; args.preparedArguments[paramIndex] = sourceValue; // } } catch (TypeMismatchException ex) { throw new UnsatisfiedDependencyException(beanName, paramIndex, paramType, "无法将请求的参数 [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] " + "转换为 " + methodType + "需要的参数类型[" + paramType.getName() + "]: " + ex.getMessage()); } } args.arguments[paramIndex] = convertedValue; args.rawArguments[paramIndex] = originalValue; } for (String autowiredBeanName : autowiredBeanNames) { if (this.beanFactory.log.isDebugEnabled()) { this.beanFactory.log.debug("Autowiring by type from bean name '" + beanName + "' via " + methodType + " to bean named '" + autowiredBeanName + "'"); } } return args; } /** * 将参数转换为member需要的类型 */ private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Member methodOrCtor, Object[] argsToResolve) { Class<?>[] paramTypes = (methodOrCtor instanceof Method ? ((Method) methodOrCtor).getParameterTypes() : ((Constructor<?>) methodOrCtor).getParameterTypes()); TypeConverter converter = bw; BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter); Object[] resolvedArgs = new Object[argsToResolve.length]; for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) { Object argValue = argsToResolve[argIndex]; MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, argIndex); GenericTypeResolver.resolveParameterType(methodParam, methodOrCtor.getDeclaringClass()); if (argValue instanceof BeanMetadataElement) { argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue); } Class<?> paramType = paramTypes[argIndex]; try { resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam); } catch (TypeMismatchException ex) { String methodType = (methodOrCtor instanceof Constructor ? "构造函数" : "工厂方法"); throw new UnsatisfiedDependencyException(beanName, argIndex, paramType, "无法将给定的参数[" + ObjectUtils.nullSafeClassName(argValue) + "]转换为" + methodType + " 需要的参数类型 [" + paramType.getName() + "]: " + ex.getMessage()); } } return resolvedArgs; } /** * 内部类,用于保存参数组合 */ private static class ArgumentsHolder { public final Object rawArguments[]; public final Object arguments[]; public final Object preparedArguments[]; public boolean resolveNecessary = false; public ArgumentsHolder(int size) { this.rawArguments = new Object[size]; this.arguments = new Object[size]; this.preparedArguments = new Object[size]; } public int getTypeDifferenceWeight(Class<?>[] paramTypes) { // If valid arguments found, determine type difference weight. // Try type difference weight on both the converted arguments and // the raw arguments. If the raw weight is better, use it. // Decrease raw weight by 1024 to prefer it over equal converted // weight. int typeDiffWeight = getTypeDifferenceWeight(paramTypes, this.arguments); int rawTypeDiffWeight = getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024; return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight); } public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) { synchronized (mbd.constructorArgumentLock) { mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod; mbd.constructorArgumentsResolved = true; if (this.resolveNecessary) { mbd.preparedConstructorArguments = this.preparedArguments; } else { mbd.resolvedConstructorArguments = this.arguments; } } } /** * Algorithm that judges the match between the declared parameter types of a candidate method * and a specific list of arguments that this method is supposed to be invoked with. * <p>Determines a weight that represents the class hierarchy difference between types and * arguments. A direct match, i.e. type Integer -> arg of class Integer, does not increase * the result - all direct matches means weight 0. A match between type Object and arg of * class Integer would increase the weight by 2, due to the superclass 2 steps up in the * hierarchy (i.e. Object) being the last one that still matches the required type Object. * Type Number and class Integer would increase the weight by 1 accordingly, due to the * superclass 1 step up the hierarchy (i.e. Number) still matching the required type Number. * Therefore, with an arg of type Integer, a constructor (Integer) would be preferred to a * constructor (Number) which would in turn be preferred to a constructor (Object). * All argument weights get accumulated. * @param paramTypes the parameter types to match * @param args the arguments to match * @return the accumulated weight for all arguments */ public static int getTypeDifferenceWeight(Class<?>[] paramTypes, Object[] args) { int result = 0; for (int i = 0; i < paramTypes.length; i++) { if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) { return Integer.MAX_VALUE; } if (args[i] != null) { Class<?> paramType = paramTypes[i]; Class<?> superClass = args[i].getClass().getSuperclass(); while (superClass != null) { if (paramType.equals(superClass)) { result = result + 2; superClass = null; } else if (ClassUtils.isAssignable(paramType, superClass)) { result = result + 2; superClass = superClass.getSuperclass(); } else { superClass = null; } } if (paramType.isInterface()) { result = result + 1; } } } return result; } } }