Search in sources :

Example 11 with DependencyDescriptor

use of org.springframework.beans.factory.config.DependencyDescriptor 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)

Example 12 with DependencyDescriptor

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

the class DefaultListableBeanFactory method findAutowireCandidates.

/**
	 * Find bean instances that match the required type.
	 * Called during autowiring for the specified bean.
	 * @param beanName the name of the bean that is about to be wired
	 * @param requiredType the actual type of bean to look for
	 * (may be an array component type or collection element type)
	 * @param descriptor the descriptor of the dependency to resolve
	 * @return a Map of candidate names and candidate instances that match
	 * the required type (never {@code null})
	 * @throws BeansException in case of errors
	 * @see #autowireByType
	 * @see #autowireConstructor
	 */
protected Map<String, Object> findAutowireCandidates(String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, descriptor.isEager());
    Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
    for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
        if (autowiringType.isAssignableFrom(requiredType)) {
            Object autowiringValue = this.resolvableDependencies.get(autowiringType);
            autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
            if (requiredType.isInstance(autowiringValue)) {
                result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                break;
            }
        }
    }
    for (String candidate : candidateNames) {
        if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
        }
    }
    if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
        // Consider fallback matches if the first pass failed to find anything...
        DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
        for (String candidate : candidateNames) {
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
                addCandidateEntry(result, candidate, descriptor, requiredType);
            }
        }
        if (result.isEmpty()) {
            // but in the case of a dependency collection, not the very same bean itself.
            for (String candidate : candidateNames) {
                if (isSelfReference(beanName, candidate) && (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) && isAutowireCandidate(candidate, fallbackDescriptor)) {
                    addCandidateEntry(result, candidate, descriptor, requiredType);
                }
            }
        }
    }
    return result;
}
Also used : DependencyDescriptor(org.springframework.beans.factory.config.DependencyDescriptor) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

DependencyDescriptor (org.springframework.beans.factory.config.DependencyDescriptor)12 Test (org.junit.Test)8 ConstructorArgumentValues (org.springframework.beans.factory.config.ConstructorArgumentValues)8 MethodParameter (org.springframework.core.MethodParameter)5 Ignore (org.junit.Ignore)3 LocalVariableTableParameterNameDiscoverer (org.springframework.core.LocalVariableTableParameterNameDiscoverer)2 PropertyDescriptor (java.beans.PropertyDescriptor)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedHashSet (java.util.LinkedHashSet)1 BeansException (org.springframework.beans.BeansException)1 TypeConverter (org.springframework.beans.TypeConverter)1 NoSuchBeanDefinitionException (org.springframework.beans.factory.NoSuchBeanDefinitionException)1 UnsatisfiedDependencyException (org.springframework.beans.factory.UnsatisfiedDependencyException)1 PriorityOrdered (org.springframework.core.PriorityOrdered)1 SynthesizingMethodParameter (org.springframework.core.annotation.SynthesizingMethodParameter)1