1. 程式人生 > >Spring IOC原理原始碼解析(@Autowired原理詳解 :標識屬性與方法)(二 )

Spring IOC原理原始碼解析(@Autowired原理詳解 :標識屬性與方法)(二 )

原始碼推薦看這篇部落格的時候開啟Spring原始碼,一邊看原始碼,一邊看部落格上程式碼的關鍵處的註釋,這樣能更好的理解Spring IOC的流程及內部實現和使用方法。如果你對IOC的原理有些瞭解,則這些註釋能幫你更深入的理解其實現方式。

Spring容器在每個Bean例項化之後,呼叫AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法:

程式碼塊1


public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
@Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if (beanType != null) { //搜尋每個Bean內@Autowired註解的資訊 InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null
); metadata.checkConfigMembers(beanDefinition); } } private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } try { //解析@Autowired註解的資訊,生成元資料,快取起來 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } catch (NoClassDefFoundError err) { throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() + "] for autowiring metadata: could not find class that it depends on", err); } } } } return metadata; } private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); Class<?> targetClass = clazz; do { final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>(); ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { //如果類內的屬性上有@Autowired註解,則用工具類獲取註解資訊 AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { //@Autowired註解不支援靜態方法 if (Modifier.isStatic(field.getModifiers())) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation is not supported on static fields: " + field); } return; } //獲取@Autowired註解的required的屬性值,如果true,但注入失敗會丟擲異常,false則不會 boolean required = determineRequiredStatus(ann); currElements.add(new **AutowiredFieldElement**(field, required)); } } }); ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() { @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } //如果方法上有@Autowired註解,則獲取註解資訊 AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { //@Autowired不支援靜態方法 if (Modifier.isStatic(method.getModifiers())) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation is not supported on static methods: " + method); } return; } //@Autowired註解標識在方法上的目的就是將容器內的Bean注入到方法的引數中,沒有引數就違背了初衷 if (method.getParameterTypes().length == 0) { if (logger.isWarnEnabled()) { logger.warn("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new **AutowiredMethodElement**(method, required, pd)); } } }); elements.addAll(0, currElements); //在解析完Bean的型別之後,遞迴的解析其父類,將所有的@Autowired的屬性和方法收集起來, //且類的層級越高其屬性會被越優先注入 **targetClass = targetClass.getSuperclass()**; } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); } }

在將@Autowired註解的資訊解析成元資料之後,快取起來,以備複用,每一個類只解析一次。

在BeanPostProcessor的postProcessMergedBeanDefinition()方法執行之後,下一步就是執行postProcessPropertyValues()方法,AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues()方法就是從Spring IOC容器從找到合適的Bean,注入屬性。找到合適的Bean,注入@Autowired標識方法的引數,然後執行此方法。

程式碼塊2

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
        implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {

    @Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
        //從快取中找到此類的@Autowired元資料,嘗試注入。沒有@Autowired則會略過
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }
        catch (BeanCreationException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
        }
        return pvs;
    }
}

InjectionMetadata,持有待注入的元資料資訊,執行inject()方法,開始注入屬性或方法引數。

程式碼塊3

public class InjectionMetadata {

    private static final Log logger = LogFactory.getLog(InjectionMetadata.class);

    private final Class<?> targetClass;
    //待注入的屬性,是一個InjectedElement集合,按類等層級排列,父類的@Autowired排前
    private final Collection<InjectedElement> injectedElements;

    private volatile Set<InjectedElement> checkedElements;


    public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
        this.targetClass = targetClass;
        this.injectedElements = elements;
    }

    public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> elementsToIterate =
                (this.checkedElements != null ? this.checkedElements : this.injectedElements);
        if (!elementsToIterate.isEmpty()) {
            boolean debug = logger.isDebugEnabled();
            for (InjectedElement element : elementsToIterate) {
                if (debug) {
                    logger.debug("Processing injected element of bean '" + beanName + "': " + element);
                }
                //解析@Autowired註解生成的元資料類有AutowiredFieldElement,AutowiredMethodElement
                //這兩個類繼承InjectionMetadata .InjectedElement,各自實現了inject方法。
                //這兩個類是AutowiredAnnotationBeanPostProcessor的私有內部類
                element.inject(target, beanName, pvs);
            }
        }
    }
}

下面先看屬性的注入:

程式碼塊4

private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {

        private final boolean required;

        private volatile boolean cached = false;

        private volatile Object cachedFieldValue;

        public AutowiredFieldElement(Field field, boolean required) {
            super(field, null);
            this.required = required;
        }

        @Override
        protected void inject(Object bean, String beanName, 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<String>(1);
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                try {
                    //如果@Autowired標識的屬性有一個合適的待注入物件,則快取這個Bean的名稱,
                    //如果再次生成這個Bean時,就不需要重新按型別去搜索Spring容器,直接獲取這個快取Bean的名稱
                    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;
                            //註冊Bean依賴
                            registerDependentBeans(beanName, autowiredBeanNames);
                            if (autowiredBeanNames.size() == 1) {
                                String autowiredBeanName = autowiredBeanNames.iterator().next();
                                if (beanFactory.containsBean(autowiredBeanName)) {
                                    //@Autowired標識屬性型別和Bean的型別要匹配,因此Array,Collection,Map型別的屬性不支援快取屬性Bean名稱
                                    if (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);  //通過反射為屬性賦值
            }
        }
    }

接下來就需要Spring IOC容器根據DependencyDescriptor依賴描述去尋找容器中合適的Bean:

程式碼塊5

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

        descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
        if (javaUtilOptionalClass == descriptor.getDependencyType()) {
            return new OptionalDependencyFactory().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 Jsr330ProviderFactory().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, String beanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

        InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
        try { //如果是快捷方式的依賴描述,則直接通過候選者的名稱來擇取Bean,返回
            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()));
            }
            //如果標識@Autowired註解的屬性是容器型別,Array,Collection,Map,則在這個方法中解析,
            //如果型別是容器型別,且返回了合適的Bean,則解析成功,程式碼詳解請看此段程式碼的下一段程式碼
            Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
            if (multipleBeans != null) { //如果確實時容器型別的屬性,則直接返回
                return multipleBeans;
            }
            //非容器型別屬性,按型別去IOC容器內擇取所有型別匹配的候選者
            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) { //如果沒有合適的Bean,但註解的required = true,則丟擲異常,若required = false,則注入失敗。
                if (descriptor.isRequired()) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                return null;
            }

            String autowiredBeanName;
            Object instanceCandidate;

            if (matchingBeans.size() > 1) {
                //非容器屬性,但是有多個候選者,此時需要從中選出最優的那個,程式碼詳解看程式碼塊9
                autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
                        return descriptor.resolveNotUnique(type, 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);
            }
            return (instanceCandidate instanceof Class ?
                    descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
        }
        finally {
            ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
        }
    }

}

Spring IOC容器解析Array,Collection,Map型別的屬性注入:

程式碼塊6

private Object resolveMultipleBeans(DependencyDescriptor descriptor, String beanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) {

        Class<?> type = descriptor.getDependencyType();
        if (type.isArray()) {  //如果@Autowired標識的是陣列型別的屬性
            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;
            } //通過型別去IOC容器內擇取符合的Bean都是使用這個方法,很重要,此方法請看此段程式碼的下一段
            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());
            //將得到的Bean的候選者們轉換為屬性型別,如從set轉換為Array,List等
            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()) {
            //獲取Collection的泛型
            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;
        }
    }

Spring IOC容器通過型別到容器呢擇取符合的Bean的方法:

程式碼塊7

protected Map<String, Object> findAutowireCandidates(
            String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
        //Spring容IOC容器中獲取所有的符合型別的Bean,包括非Singleton的scope,
        //也就是說request,session,prototype的均會被例項化,
        //request,session如果此時被例項化會報異常,因為這兩個作用域的Bean實際是儲存在HttpRequest中的,
        //此時還沒有Http請求,如果是FactoryBean,則匹配getObject()放回的型別
        String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this, requiredType, true, descriptor.isEager());
        Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
        //首先從容器自身註冊了的依賴解析來匹配,Spring容器自身註冊了很多Bean的依賴,
        //當使用者想要注入指定型別的Bean時,會優先從已註冊的依賴內尋找匹配,這點很重要,程式碼詳解請看此段下一段。
        for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
            if (autowiringType.isAssignableFrom(requiredType)) {
                Object autowiringValue = this.resolvableDependencies.get(autowiringType);
                autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
                //如果註冊的依賴Bean型別時指定型別的例項或是其父類,介面,則將其作為候選者,註冊依賴的型別不會重複
                if (requiredType.isInstance(autowiringValue)) {
                    result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
                    break;
                }
            }
        }
        for (String candidate : candidateNames) {
            //@Autowried標識的屬性不能和定義其的類的型別相同,就是類不能再注入相同類,會觸發無限遞迴注入
            if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, 
                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()) {
                // 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;
    }

        /**
     * Add an entry to the candidate map: a bean instance if available or just the resolved
     * type, preventing early bean initialization ahead of primary candidate selection.
     */
    private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
            DependencyDescriptor descriptor, Class<?> requiredType) {
        //當@Autowired標識的是容器型別的屬性,生成的依賴描述型別是MultiElementDescriptor ,
        //因此所有的候選者均是合格的,所以會當場例項化他們。而如果屬性的型別非容器,那麼可能是多個候選者中挑一個,
        //此時例項化他們所有就不合適了,最終會把合格的那個例項化,如果沒有合格的則不例項化,
        //提前例項化對Bean的很多方面有影響,比如AOP,EarlyReference等 */
        if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
            candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
        }
        else {
            candidates.put(candidateName, getType(candidateName));
        }
    }

如下程式碼所示,Spring在開始例項化Bean之前,已經註冊了很多Bean的歷依賴關係對,當@Autowired標識的屬性型別是已經註冊了的依賴型別,則將這些註冊的物件作為候選者。這些物件並不一定是容器內的Bean,比如Http請求相關的物件,他們被注入的優先順序比容器內Bean高。同時也忽略了一些依賴關係,也就是有些型別的Bean不允許被注入,這個實現方式稍後會看到

程式碼塊8

public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext, DisposableBean {

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    }
}

public abstract class WebApplicationContextUtils {

        public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
        beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
        beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
        beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
        if (sc != null) {
            ServletContextScope appScope = new ServletContextScope(sc);
            beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
            // Register as ServletContext attribute, for ContextCleanupListener to detect it.
            sc.setAttribute(ServletContextScope.class.getName(), appScope);
        }

        beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
        beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
        beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
        beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
        if (jsfPresent) {
            FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
        }
    }

}

普通屬性輸入,但是候選者有多個,如何從中挑選出最優解.

程式碼塊9


    protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
        Class<?> requiredType = descriptor.getDependencyType();
        //根據@Primary註解來擇取最優解
        String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
        if (primaryCandidate != null) {
            return primaryCandidate;
        }
        //根據@Order,@PriorityOrder,及實現Order介面的序號來擇取最優解
        String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
        if (priorityCandidate != null) {
            return priorityCandidate;
        }
        // Fallback
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateName = entry.getKey();
            Object beanInstance = entry.getValue();

            //如果通過以上兩步都不能選擇出最優解,則使用最基本的策略
            //首先如果這個型別已經由Spring註冊過依賴關係對,則直接使用註冊的物件,
            //候選者集合是LinkedHashMap,有序Map集合,容器註冊的依賴物件位於LinkedHashMap的起始位置
            //如果沒有註冊過此型別的依賴關係,則根據屬性的名稱來匹配,、
            //如果屬性名稱和某個候選者的Bean名稱或別名一致,那麼直接將此Bean作為最優解
            if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
                    matchesBeanName(candidateName, descriptor.getDependencyName())) {
                return candidateName;
            }
        }
        return null;
    }


    protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
        String primaryBeanName = null;
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateBeanName = entry.getKey();
            Object beanInstance = entry.getValue();
            //候選者可以是父容器內的標識了@Primary的Bean,也可以是當前容器的。SpringMVC容器將Spring容器作為父容器
            if (isPrimary(candidateBeanName, beanInstance)) {
                if (primaryBeanName != null) {
                    boolean candidateLocal = containsBeanDefinition(candidateBeanName);
                    boolean primaryLocal = containsBeanDefinition(primaryBeanName);
                    //此處確保同一個容器中同一個型別的多個Bean最多隻有一個Bean標識了@Primary
                    if (candidateLocal && primaryLocal) {
                        throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                                "more than one 'primary' bean found among candidates: " + candidates.keySet());
                    }
                    //如果上一個@Primary的Bean是父容器的,則用當前容器的候選者覆蓋之前的@Primary的Bean
                    else if (candidateLocal) {
                        primaryBeanName = candidateBeanName;
                    }
                }
                else {
                    primaryBeanName = candidateBeanName;
                }
            }
        }
        return primaryBeanName;
    }

    protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
        String highestPriorityBeanName = null;
        Integer highestPriority = null;
        for (Map.Entry<String, Object> entry : candidates.entrySet()) {
            String candidateBeanName = entry.getKey();
            Object beanInstance = entry.getValue();
            Integer candidatePriority = getPriority(beanInstance);
            if (candidatePriority != null) {
                if (highestPriorityBeanName != null) {
                    //不能同時存在兩個最高優先順序的序號
                    if (candidatePriority.equals(highestPriority)) {
                        throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                                "Multiple beans found with the same priority ('" + highestPriority +
                                "') among candidates: " + candidates.keySet());
                    } //使用優先順序序號最小的Bean作為最優解
                    else if (candidatePriority < highestPriority) {
                        highestPriorityBeanName = candidateBeanName;
                        highestPriority = candidatePriority;
                    }
                }
                else {
                    highestPriorityBeanName = candidateBeanName;
                    highestPriority = candidatePriority;
                }
            }
        }
        return highestPriorityBeanName;
    }

@Autowired標識方法的解析過程和標識屬性類似,程式碼詳解如下:

private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {

        private final boolean required;

        private volatile boolean cached = false;

        private volatile Object[] cachedMethodArguments;

        public AutowiredMethodElement(Method method, boolean required, PropertyDescriptor pd) {
            super(method, pd);
            this.required = required;
        }

        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            if (checkPropertySkipping(pvs)) {
                return;
            }
            Method method = (Method) this.member;
            Object[] arguments;
            if (this.cached) { //如果已經解析過,且快取了方法的引數注入,則不需要再次解析
                // Shortcut for avoiding synchronization...
                arguments = resolveCachedArguments(beanName);
            }
            else {
                Class<?>[] paramTypes = method.getParameterTypes();
                arguments = new Object[paramTypes.length];
                DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
                Set<String> autowiredBeans = new LinkedHashSet<String>(paramTypes.length);
                TypeConverter typeConverter = beanFactory.getTypeConverter();
                for (int i = 0; i < arguments.length; i++) {
                    MethodParameter methodParam = new MethodParameter(method, i);
                    DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
                    currDesc.setContainingClass(bean.getClass());
                    descriptors[i] = currDesc;
                    try { //根據引數型別從Spring容器中尋找合適的Bean
                        Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
                        //如果引數解析失敗,但是required = false,則忽略執行此方法
                        if (arg == null && !this.required) {
                            arguments = null;
                            break;
                        }
                        arguments[i] = arg;
                    }
                    catch (BeansException ex) {
                        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
                    }
                }
                synchronized (this) {
                    if (!this.cached) {
                        if (arguments != null) {
                            this.cachedMethodArguments = new Object[paramTypes.length];
                            for (int i = 0; i < arguments.length; i++) {
                                this.cachedMethodArguments[i] = descriptors[i];
                            }
                            registerDependentBeans(beanName, autowiredBeans);
                            if (autowiredBeans.size() == paramTypes.length) {
                                Iterator<String> it = autowiredBeans.iterator();
                                for (int i = 0; i < paramTypes.length; i++) {
                                    String autowiredBeanName = it.next();
                                    if (beanFactory.containsBean(autowiredBeanName)) {
                                        if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
                                            this.cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
                                                    descriptors[i], autowiredBeanName, paramTypes[i]);
                                        }
                                    }
                                }
                            }
                        }
                        else {
                            this.cachedMethodArguments = null;
                        }
                        this.cached = true;
                    }
                }
            }
            if (arguments != null) {
                try {
                    ReflectionUtils.makeAccessible(method);
                    //引數解析完畢,執行此方法。@Autowired標識的方法執行的比@PostConstruct早
                    method.invoke(bean, arguments);  
                }
                catch (InvocationTargetException ex){
                    throw ex.getTargetException();
                }
            }
        }

        private Object[] resolveCachedArguments(String beanName) {
            if (this.cachedMethodArguments == null) {
                return null;
            }
            Object[] arguments = new Object[this.cachedMethodArguments.length];
            for (int i = 0; i < arguments.length; i++) {
                arguments[i] = resolvedCachedArgument(beanName, this.cachedMethodArguments[i]);
            }
            return arguments;
        }
    }