Search in sources :

Example 1 with InjectionPoint

use of org.springframework.beans.factory.InjectionPoint in project spring-framework by spring-projects.

the class DefaultListableBeanFactory method doResolveDependency.

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }
        Class<?> type = descriptor.getDependencyType();
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }
        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
            if (descriptor.isRequired()) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }
        String autowiredBeanName;
        Object instanceCandidate;
        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(type, matchingBeans);
                } else {
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        } else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        return (instanceCandidate instanceof Class ? descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
    } finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}
Also used : TypeConverter(org.springframework.beans.TypeConverter) InjectionPoint(org.springframework.beans.factory.InjectionPoint) BeanDefinition(org.springframework.beans.factory.config.BeanDefinition) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 2 with InjectionPoint

use of org.springframework.beans.factory.InjectionPoint in project spring-framework by spring-projects.

the class ConstructorResolver method createArgumentArray.

/**
	 * 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, String[] paramNames, Executable executable, boolean autowiring) throws UnsatisfiedDependencyException {
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = (customConverter != null ? customConverter : bw);
    ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
    Set<ConstructorArgumentValues.ValueHolder> usedValueHolders = new HashSet<>(paramTypes.length);
    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
        Class<?> paramType = paramTypes[paramIndex];
        String paramName = (paramNames != null ? paramNames[paramIndex] : "");
        // Try to find matching constructor argument value, either indexed or generic.
        ConstructorArgumentValues.ValueHolder valueHolder = resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
        // it could match after type conversion (for example, String -> int).
        if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
            valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
        }
        if (valueHolder != null) {
            // 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();
                MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
                try {
                    convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
                    // TODO re-enable once race condition has been found (SPR-7423)
                    /*
						if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
							// Either a converted value or still the original one: store converted value.
							sourceHolder.setConvertedValue(convertedValue);
							args.preparedArguments[paramIndex] = convertedValue;
						}
						else {
						*/
                    args.resolveNecessary = true;
                    args.preparedArguments[paramIndex] = sourceValue;
                // }
                } catch (TypeMismatchException ex) {
                    throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(valueHolder.getValue()) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
                }
            }
            args.arguments[paramIndex] = convertedValue;
            args.rawArguments[paramIndex] = originalValue;
        } else {
            MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
            // have to fail creating an argument array for the given constructor.
            if (!autowiring) {
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?");
            }
            try {
                Object autowiredArgument = resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter);
                args.rawArguments[paramIndex] = autowiredArgument;
                args.arguments[paramIndex] = autowiredArgument;
                args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
                args.resolveNecessary = true;
            } catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
            }
        }
    }
    for (String autowiredBeanName : autowiredBeanNames) {
        this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
        if (this.beanFactory.logger.isDebugEnabled()) {
            this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName + "' via " + (executable instanceof Constructor ? "constructor" : "factory method") + " to bean named '" + autowiredBeanName + "'");
        }
    }
    return args;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) InjectionPoint(org.springframework.beans.factory.InjectionPoint) Constructor(java.lang.reflect.Constructor) TypeMismatchException(org.springframework.beans.TypeMismatchException) ValueHolder(org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder) ValueHolder(org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder) InjectionPoint(org.springframework.beans.factory.InjectionPoint) ConstructorArgumentValues(org.springframework.beans.factory.config.ConstructorArgumentValues) TypeConverter(org.springframework.beans.TypeConverter) UnsatisfiedDependencyException(org.springframework.beans.factory.UnsatisfiedDependencyException) MethodParameter(org.springframework.core.MethodParameter) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) BeansException(org.springframework.beans.BeansException)

Example 3 with InjectionPoint

use of org.springframework.beans.factory.InjectionPoint in project spring-framework by spring-projects.

the class ConstructorResolver method resolvePreparedArguments.

/**
	 * Resolve the prepared arguments stored in the given bean definition.
	 */
private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw, Executable executable, Object[] argsToResolve) {
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = (customConverter != null ? customConverter : bw);
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    Class<?>[] paramTypes = executable.getParameterTypes();
    Object[] resolvedArgs = new Object[argsToResolve.length];
    for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
        Object argValue = argsToResolve[argIndex];
        MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
        GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
        if (argValue instanceof AutowiredArgumentMarker) {
            argValue = resolveAutowiredArgument(methodParam, beanName, null, converter);
        } else if (argValue instanceof BeanMetadataElement) {
            argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
        } else if (argValue instanceof String) {
            argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
        }
        Class<?> paramType = paramTypes[argIndex];
        try {
            resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
        } catch (TypeMismatchException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) + "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
        }
    }
    return resolvedArgs;
}
Also used : InjectionPoint(org.springframework.beans.factory.InjectionPoint) TypeMismatchException(org.springframework.beans.TypeMismatchException) InjectionPoint(org.springframework.beans.factory.InjectionPoint) TypeConverter(org.springframework.beans.TypeConverter) BeanMetadataElement(org.springframework.beans.BeanMetadataElement) UnsatisfiedDependencyException(org.springframework.beans.factory.UnsatisfiedDependencyException) MethodParameter(org.springframework.core.MethodParameter)

Aggregations

TypeConverter (org.springframework.beans.TypeConverter)3 InjectionPoint (org.springframework.beans.factory.InjectionPoint)3 TypeMismatchException (org.springframework.beans.TypeMismatchException)2 UnsatisfiedDependencyException (org.springframework.beans.factory.UnsatisfiedDependencyException)2 MethodParameter (org.springframework.core.MethodParameter)2 Constructor (java.lang.reflect.Constructor)1 HashSet (java.util.HashSet)1 IdentityHashMap (java.util.IdentityHashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 BeanMetadataElement (org.springframework.beans.BeanMetadataElement)1 BeansException (org.springframework.beans.BeansException)1 BeanDefinition (org.springframework.beans.factory.config.BeanDefinition)1 ConstructorArgumentValues (org.springframework.beans.factory.config.ConstructorArgumentValues)1 ValueHolder (org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder)1