• spring bean自动装配


    说到spring自动装配的bean大伙都比较了解,@Autowired不就完了么。哈哈,今天我在review的时候发现了这个问题,小伙伴看下代码:

    @Bean
        public List<PlatformCheck> platformCheckList() {
            Map<String, PlatformCheck> result = applicationContext.getBeansOfType(PlatformCheck.class);
            List<PlatformCheck> list = new ArrayList<>(result.values());
            list.sort(Comparator.comparingInt(PlatformCheck::getOrder));
            for (int i = 0; i < list.size(); i++) {
                PlatformCheck platformCheck = list.get(i);
                log.info("PlatformCheck类:{} 已经加载, order:{}", platformCheck.getClass().getName(), platformCheck.getOrder());
            }
            return list;
        }

    上面代码配置一个bean

    @Component
    public class AuthenticationHandler {
        private final Logger log = LoggerFactory.getLogger(AuthenticationHandler.class);
        @Autowiredpublic List<PlatformCheck> platformCheckList;
        public List<Function<ContextBridge, Boolean>> loginContextInitialization;
        @Autowired
        public LoginContextCollection loginContextCollection;

    上面的代码将配置的bean自动注入进来。上面的程序会正确运行么?

    突然看上去其实就有些心里疑问的,List<PlatformCheck>一定会被注册进来;但是注册究竟是不是上面配置的名为platformCheckList这个bean呢。

    答案在这:

    populateBean
    默认6个beanPostProcess的第5个:AutowiredAnnotationBeanPostProcessor#postProcessProperties
    AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
    AutowiredAnnotationBeanPostProcessor#inject方法中开始遍历成员变量,开始真正的注入流程。
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Collection<InjectedElement> checkedElements = this.checkedElements;
            Collection<InjectedElement> elementsToIterate =
                    (checkedElements != null ? checkedElements : this.injectedElements);
            if (!elementsToIterate.isEmpty()) {
                for (InjectedElement element : elementsToIterate) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Processing injected element of bean '" + beanName + "': " + element);
                    }
                    element.inject(target, beanName, pvs);
                }
            }
        }
    还会进入第二个AutowiredAnnotationBeanPostProcessor#inject方法:
    @Override
            protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
                Field field = (Field) this.member;
                Object value;
                if (this.cached) {
                    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
                }
                else {
                    DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
                    desc.setContainingClass(bean.getClass());
                    Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
                    Assert.state(beanFactory != null, "No BeanFactory available");
                    TypeConverter typeConverter = beanFactory.getTypeConverter();
                    try {
                        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
                    }
                    catch (BeansException ex) {
                        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
                    }
                    synchronized (this) {
                        if (!this.cached) {
                            if (value != null || this.required) {
                                this.cachedFieldValue = desc;
                                registerDependentBeans(beanName, autowiredBeanNames);
                                if (autowiredBeanNames.size() == 1) {
                                    String autowiredBeanName = autowiredBeanNames.iterator().next();
                                    if (beanFactory.containsBean(autowiredBeanName) &&
                                            beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                        this.cachedFieldValue = new ShortcutDependencyDescriptor(
                                                desc, autowiredBeanName, field.getType());
                                    }
                                }
                            }
                            else {
                                this.cachedFieldValue = null;
                            }
                            this.cached = true;
                        }
                    }
                }
                if (value != null) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(bean, value);
                }
            }
        }
    DefaultListableBeanFactory#resolveDependency,进入else。
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    
            descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
            if (Optional.class == descriptor.getDependencyType()) {
                return createOptionalDependency(descriptor, requestingBeanName);
            }
            else if (ObjectFactory.class == descriptor.getDependencyType() ||
                    ObjectProvider.class == descriptor.getDependencyType()) {
                return new DependencyObjectProvider(descriptor, requestingBeanName);
            }
            else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
            }
            else {
                Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                        descriptor, requestingBeanName);
                if (result == null) {
                    result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
                }
                return result;
            }
        }
    DefaultListableBeanFactory#doResolveDependency,进入之后会判断当前的属性的类型:
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
                @Nullable Set<String> autowiredBeanNames, @Nullable 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());
                    try {
                        return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
                    }
                    catch (UnsupportedOperationException ex) {
                        // A custom TypeConverter which does not support TypeDescriptor resolution...
                        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 (isRequired(descriptor)) {
                        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    return null;
                }
    
                String autowiredBeanName;
                Object instanceCandidate;
    
                if (matchingBeans.size() > 1) {
                    autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                    if (autowiredBeanName == null) {
                        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
                            return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
                        }
                        else {
                            // In case of an optional Collection/Map, silently ignore a non-unique case:
                            // possibly it was meant to be an empty collection of multiple regular beans
                            // (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);
                }
                if (instanceCandidate instanceof Class) {
                    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
                }
                Object result = instanceCandidate;
                if (result instanceof NullBean) {
                    if (isRequired(descriptor)) {
                        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                    }
                    result = null;
                }
                if (!ClassUtils.isAssignableValue(type, result)) {
                    throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
                }
                return result;
            }
            finally {
                ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
            }
        }
    DefaultListableBeanFactory#resolveMultipleBeans,进入如果是List就会去找多个bean进行匹配:
    private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
                @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
    
            final Class<?> type = descriptor.getDependencyType();
    
            if (descriptor instanceof StreamDependencyDescriptor) {
                Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
                if (autowiredBeanNames != null) {
                    autowiredBeanNames.addAll(matchingBeans.keySet());
                }
                Stream<Object> stream = matchingBeans.keySet().stream()
                        .map(name -> descriptor.resolveCandidate(name, type, this))
                        .filter(bean -> !(bean instanceof NullBean));
                if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
                    stream = stream.sorted(adaptOrderComparator(matchingBeans));
                }
                return stream;
            }
            else if (type.isArray()) {
                Class<?> componentType = type.getComponentType();
                ResolvableType resolvableType = descriptor.getResolvableType();
                Class<?> resolvedArrayType = resolvableType.resolve(type);
                if (resolvedArrayType != type) {
                    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(), resolvedArrayType);
                if (result instanceof Object[]) {
                    Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
                    if (comparator != null) {
                        Arrays.sort((Object[]) result, comparator);
                    }
                }
                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 (result instanceof List) {
                    Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
                    if (comparator != null) {
                        ((List<?>) result).sort(comparator);
                    }
                }
                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;
            }
        }
    
    DefaultListableBeanFactory#findAutowireCandidates,寻找自动注入的后续bean
    protected Map<String, Object> findAutowireCandidates(
                @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    
            String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                    this, requiredType, true, descriptor.isEager());
            Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
            for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
                Class<?> autowiringType = classObjectEntry.getKey();
                if (autowiringType.isAssignableFrom(requiredType)) {
                    Object autowiringValue = classObjectEntry.getValue();
                    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()) {
                boolean multiple = 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) &&
                            (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
                        addCandidateEntry(result, candidate, descriptor, requiredType);
                    }
                }
                if (result.isEmpty() && !multiple) {
                    // Consider self references as a final pass...
                    // 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;
        }
    
    doResolveDependency核心逻辑还是看下这里,如果是List类型接口装配,使用指定具体bean名称,Object multipleBeans = resolveMultipleBeans这个方法会返回null
    那么接下来会在Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);方法中找到实际的bean的名称去装配。
    如果没有指定bean的名称进行装配,代码就会走到findAutowireCandidates方法的这个位置:
    for (String candidate : candidateNames) {
                if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
                    addCandidateEntry(result, candidate, descriptor, requiredType);
                }
            }
    那么有几个类型,就会被add进List。
  • 相关阅读:
    spring无法接收上传文件
    springcloud feign增加熔断器Hystrix
    mybatis调用存储过程(@Select方式)
    spring在注解标注的方法上加切面
    java注解Annotation
    java包装类
    JZ-C-43
    JZ-C-42-Plus
    JZ-C-42
    JZ-C-41-Plus
  • 原文地址:https://www.cnblogs.com/zzq-include/p/13183060.html
Copyright © 2020-2023  润新知