Search in sources :

Example 6 with TypeConverter

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

the class ArgumentConvertingMethodInvoker method doFindMatchingMethod.

/**
	 * Actually find a method with matching parameter type, i.e. where each
	 * argument value is assignable to the corresponding parameter type.
	 * @param arguments the argument values to match against method parameters
	 * @return a matching method, or {@code null} if none
	 */
protected Method doFindMatchingMethod(Object[] arguments) {
    TypeConverter converter = getTypeConverter();
    if (converter != null) {
        String targetMethod = getTargetMethod();
        Method matchingMethod = null;
        int argCount = arguments.length;
        Method[] candidates = ReflectionUtils.getAllDeclaredMethods(getTargetClass());
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Object[] argumentsToUse = null;
        for (Method candidate : candidates) {
            if (candidate.getName().equals(targetMethod)) {
                // Check if the inspected method has the correct number of parameters.
                Class<?>[] paramTypes = candidate.getParameterTypes();
                if (paramTypes.length == argCount) {
                    Object[] convertedArguments = new Object[argCount];
                    boolean match = true;
                    for (int j = 0; j < argCount && match; j++) {
                        // Verify that the supplied argument is assignable to the method parameter.
                        try {
                            convertedArguments[j] = converter.convertIfNecessary(arguments[j], paramTypes[j]);
                        } catch (TypeMismatchException ex) {
                            // Ignore -> simply doesn't match.
                            match = false;
                        }
                    }
                    if (match) {
                        int typeDiffWeight = getTypeDifferenceWeight(paramTypes, convertedArguments);
                        if (typeDiffWeight < minTypeDiffWeight) {
                            minTypeDiffWeight = typeDiffWeight;
                            matchingMethod = candidate;
                            argumentsToUse = convertedArguments;
                        }
                    }
                }
            }
        }
        if (matchingMethod != null) {
            setArguments(argumentsToUse);
            return matchingMethod;
        }
    }
    return null;
}
Also used : TypeConverter(org.springframework.beans.TypeConverter) SimpleTypeConverter(org.springframework.beans.SimpleTypeConverter) TypeMismatchException(org.springframework.beans.TypeMismatchException) Method(java.lang.reflect.Method)

Example 7 with TypeConverter

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

the class ConstructorResolver method resolveConstructorArguments.

/**
	 * Resolve the constructor arguments for this bean into the resolvedValues object.
	 * This may involve looking up other beans.
	 * <p>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 customConverter = this.beanFactory.getCustomTypeConverter();
    TypeConverter converter = (customConverter != null ? customConverter : 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(mbd.getResourceDescription(), beanName, "Invalid constructor argument index: " + index);
        }
        if (index > minNrOfArgs) {
            minNrOfArgs = index + 1;
        }
        ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
        if (valueHolder.isConverted()) {
            resolvedValues.addIndexedArgumentValue(index, valueHolder);
        } else {
            Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
            ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
            resolvedValueHolder.setSource(valueHolder);
            resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
        }
    }
    for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
        if (valueHolder.isConverted()) {
            resolvedValues.addGenericArgumentValue(valueHolder);
        } else {
            Object resolvedValue = valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
            ConstructorArgumentValues.ValueHolder resolvedValueHolder = new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
            resolvedValueHolder.setSource(valueHolder);
            resolvedValues.addGenericArgumentValue(resolvedValueHolder);
        }
    }
    return minNrOfArgs;
}
Also used : TypeConverter(org.springframework.beans.TypeConverter) BeanCreationException(org.springframework.beans.factory.BeanCreationException) ValueHolder(org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder) ValueHolder(org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder) Map(java.util.Map) InjectionPoint(org.springframework.beans.factory.InjectionPoint) ConstructorArgumentValues(org.springframework.beans.factory.config.ConstructorArgumentValues)

Example 8 with TypeConverter

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

the class DefaultListableBeanFactory method resolveMultipleBeans.

private Object resolveMultipleBeans(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
    Class<?> type = descriptor.getDependencyType();
    if (type.isArray()) {
        Class<?> componentType = type.getComponentType();
        ResolvableType resolvableType = descriptor.getResolvableType();
        Class<?> resolvedArrayType = resolvableType.resolve();
        if (resolvedArrayType != null && resolvedArrayType != type) {
            type = resolvedArrayType;
            componentType = resolvableType.getComponentType().resolve();
        }
        if (componentType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        if (getDependencyComparator() != null && result instanceof Object[]) {
            Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans));
        }
        return result;
    } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
        Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
        if (elementType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
        Object result = converter.convertIfNecessary(matchingBeans.values(), type);
        if (getDependencyComparator() != null && result instanceof List) {
            Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans));
        }
        return result;
    } else if (Map.class == type) {
        ResolvableType mapType = descriptor.getResolvableType().asMap();
        Class<?> keyType = mapType.resolveGeneric(0);
        if (String.class != keyType) {
            return null;
        }
        Class<?> valueType = mapType.resolveGeneric(1);
        if (valueType == null) {
            return null;
        }
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, new MultiElementDescriptor(descriptor));
        if (matchingBeans.isEmpty()) {
            return null;
        }
        if (autowiredBeanNames != null) {
            autowiredBeanNames.addAll(matchingBeans.keySet());
        }
        return matchingBeans;
    } else {
        return null;
    }
}
Also used : TypeConverter(org.springframework.beans.TypeConverter) List(java.util.List) ArrayList(java.util.ArrayList) ResolvableType(org.springframework.core.ResolvableType) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) LinkedHashMap(java.util.LinkedHashMap)

Example 9 with TypeConverter

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

the class SetFactoryBean method createInstance.

@Override
@SuppressWarnings("unchecked")
protected Set<Object> createInstance() {
    if (this.sourceSet == null) {
        throw new IllegalArgumentException("'sourceSet' is required");
    }
    Set<Object> result = null;
    if (this.targetSetClass != null) {
        result = BeanUtils.instantiateClass(this.targetSetClass);
    } else {
        result = new LinkedHashSet<>(this.sourceSet.size());
    }
    Class<?> valueType = null;
    if (this.targetSetClass != null) {
        valueType = ResolvableType.forClass(this.targetSetClass).asCollection().resolveGeneric();
    }
    if (valueType != null) {
        TypeConverter converter = getBeanTypeConverter();
        for (Object elem : this.sourceSet) {
            result.add(converter.convertIfNecessary(elem, valueType));
        }
    } else {
        result.addAll(this.sourceSet);
    }
    return result;
}
Also used : TypeConverter(org.springframework.beans.TypeConverter)

Example 10 with TypeConverter

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

the class AbstractAutowireCapableBeanFactory method autowireByType.

/**
	 * Abstract method defining "autowire by type" (bean properties by type) behavior.
	 * <p>This is like PicoContainer default, in which there must be exactly one bean
	 * of the property type in the bean factory. This makes bean factories simple to
	 * configure for small namespaces, but doesn't work as well as standard Spring
	 * behavior for bigger applications.
	 * @param beanName the name of the bean to autowire by type
	 * @param mbd the merged bean definition to update through autowiring
	 * @param bw BeanWrapper from which we can obtain information about the bean
	 * @param pvs the PropertyValues to register wired objects with
	 */
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // even if it technically is a unsatisfied, non-simple property.
            if (Object.class != pd.getPropertyType()) {
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" + propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                autowiredBeanNames.clear();
            }
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) PropertyDescriptor(java.beans.PropertyDescriptor) DependencyDescriptor(org.springframework.beans.factory.config.DependencyDescriptor) PriorityOrdered(org.springframework.core.PriorityOrdered) TypeConverter(org.springframework.beans.TypeConverter) UnsatisfiedDependencyException(org.springframework.beans.factory.UnsatisfiedDependencyException) MethodParameter(org.springframework.core.MethodParameter) BeansException(org.springframework.beans.BeansException)

Aggregations

TypeConverter (org.springframework.beans.TypeConverter)13 Map (java.util.Map)4 InjectionPoint (org.springframework.beans.factory.InjectionPoint)4 LinkedHashMap (java.util.LinkedHashMap)3 BeansException (org.springframework.beans.BeansException)3 SimpleTypeConverter (org.springframework.beans.SimpleTypeConverter)3 TypeMismatchException (org.springframework.beans.TypeMismatchException)3 UnsatisfiedDependencyException (org.springframework.beans.factory.UnsatisfiedDependencyException)3 MethodParameter (org.springframework.core.MethodParameter)3 ArrayList (java.util.ArrayList)2 IdentityHashMap (java.util.IdentityHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 BeanCreationException (org.springframework.beans.factory.BeanCreationException)2 ConstructorArgumentValues (org.springframework.beans.factory.config.ConstructorArgumentValues)2 ValueHolder (org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder)2 ResolvableType (org.springframework.core.ResolvableType)2 PropertyDescriptor (java.beans.PropertyDescriptor)1 Constructor (java.lang.reflect.Constructor)1 Method (java.lang.reflect.Method)1