• Spring之@Qualifier


    @Qualifier的一个典型的应用是配合@Autowired一起使用的。主要是当要进行@Autowired的字段候选bean有多个的话,使用@Qualifier可以通过BeanName指定Bean注入。

    之前有分析过@Autowired的实现原理,这部分就不赘述了

    AutowiredFieldElement.inject
    private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
    
            private final boolean required;
    
            private volatile boolean cached = false;
    
            @Nullable
            private volatile Object cachedFieldValue;
    
            public AutowiredFieldElement(Field field, boolean required) {
                super(field, null);
                this.required = required;
            }
    
            @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);
                    }
    DefaultListableBeanFactory.resolveDependency
    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;
            }
        }

      

    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;
                }
           ....

      

    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);
                    }
                }

      到这里就能看到在哪里解析的@Qualifier了

    关于 DefaultListableBeanFactory 内部的 autowireCandidateResolver 的实现类,我只能通过跟代码来观察。

    public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
            Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
            if (autowireCandidateResolver instanceof BeanFactoryAware) {
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
                }
            }
            this.autowireCandidateResolver = autowireCandidateResolver;
        }

      我在跟代码的时候跟到了这里,其中 autowireCandidateResolver 一开始是 SimpleAutowireCandidateResolver。但是代码会走到setAutowireCandidateResolver这里方法里,最后autowireCandidateResolver =  ContextAnnotationAutowireCandidateResolver

      其实SimpleAutowireCandidateResolver是没有能力处理@Qualifier的,但是ContextAnnotationAutowireCandidateResolver是有这个能力的

      

  • 相关阅读:
    java~用域名回显照片
    java~-照片--用流回显源码
    java表单+多文件上传~~源代码
    java~生成二维码源代码
    html页面悬浮框--左边动画(隐藏凸出)---css设置
    html页面悬浮框--右边动画(隐藏凸出)---css设置
    java编写二维码
    java上传---表单+多文件上传
    js--a标签带参数href取值
    爬虫杂记
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14413319.html
Copyright © 2020-2023  润新知