spring源碼學習_bean的實例化過程

上篇(spring源碼學習_bean工廠的初始化)有說到,bean工廠初始化的最後一步就是將所有剩下的,在beanDefinitionMap中註冊的,需要被實例化的bean全部實例化。其實例化過程最終是又 getBean 方法完成的,這裏我們就重點看看getBean方法。

 

1.bean的實例化過程

public<T> T getBean(String name,@Nullable Class<T> requiredType,@Nullable Object...args)throws BeansException{

    return doGetBean(name,requiredType,args,false);
}


protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        //這裏去掉工廠bean的前綴或者將別名轉化爲規範名
        final String beanName = transformedBeanName(name);
        Object bean;

        //這裏嘗試直接從singletonObjects(單例池)中獲取bean的實例
        //最終被實例化的單例bean,都會被存放在singletonObjects中
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            //如果是工廠bean,獲取工廠bean創建的bean,普通bean則直接返回
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            //如果這個bean已經在創建了,則拋出異常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            //獲取父工廠
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //當父工廠存在時,將實例化任務交給父工廠
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                //......省略
                //這裏調用了父工廠的getBean方法
            }

            if (!typeCheckOnly) {
                //將這個bean標記爲已實例化狀態
                markBeanAsCreated(beanName);
            }

            try {
                //獲取到這個bean的 beanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //這裏檢查了這個bean是否是Abstract的,是則拋出異常
                checkMergedBeanDefinition(mbd, beanName, args);
                
                //獲取到這個bean的依賴信息
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        //檢查是否已經註冊過該依賴,避免重複
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //將依賴信息註冊到 dependenciesForBeanMap 中
                        //Map<String, Set<String>> dependenciesForBeanMap 用於存放bean的依賴信息
                        registerDependentBean(dep, beanName);
                        try {
                            //遞歸實例化依賴的bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                //當所有的依賴均被實例化後,開始創建這個bean的實例
                //這裏是單例bean的初始化
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
        //......後面省略
        return (T) bean;
    }

1. getBean方法首先會調用getSingleton(beanName)方法,來判斷工廠中是否已經存在該bean的實例化對象,有則直接返回。

2. 沒有則會檢查是否存在父工廠,如果有,則將實例化bean的任務交給父工廠來完成。

3. 上面過程均失敗後,就會嘗試着創建一個bean的實例。這時會獲取到一個bean的beanDefinition,beanDefinition中包含了這個bean的相關信息。

4. spring通過beanDefinition獲取到他的依賴信息,並遞歸的將其所有的依賴實例化。需要注意的是,這裏的依賴(dependsOn)指的並不是我們bean中需要自動注入的bean。而是@DependsOn註解標註的bean,指明該bean必須優先於本bean被實例化。

5. 所有的依賴(dependsOn)均已被實例化後,調用createBean方法對bean進行實例化。

 

spring在做了一系列的準備工作後,最後調用了 createBean方法進行bean的實例化操作

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //這裏實例化了bean
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //......省略部分不重要代碼

		// Initialize the bean instance.
		Object exposedObject = bean;
        try {
            //這裏裝配了bean
            populateBean(beanName, mbd, instanceWrapper);
            //進行初始化操作
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            //。。。。。。省略			        
        }

        return exposedObject;
    }

 

這裏可以看到,createBean調用了doCreateBean方法,主要完成了三個方面的工作,

1. 找到創建這個實例的構造法方法,並通過這個構造方法創建這個實例,我們不細說。

2. 調用populateBaen方法裝配bean,我們的@Autowried註解將會在這裏發揮作用。

3. 最後就是對裝配好的bean進行初始化操作。

 

2.bean的自動裝配

這裏只展示populateBean方法部分重要的代碼

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

    //......省略了部分參數檢查和裝配的前置操作代碼

    //這裏獲取到 beanDefinition的 PropertyValues屬性
    //PropertyValues是一個用來表示Bean屬性的對象,其中定義了屬性的名字和值等信息
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    //這裏獲取到自動注入的類型  byName 或是 byType
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    //這裏通過byName 或是 byType的方式獲取到bean依賴的實例
    //並將獲取到的依賴的實例註冊到 PropertyValues屬性中 也就是這裏的newPvs
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        //賦值給pvs
        pvs = newPvs;
    }
		
    //這裏獲取到 BeanPostProcessor
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        //其中實現了 InstantiationAwareBeanPostProcessor接口的就有 AutowiredAnnotationBeanPostProcessor
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //關鍵的看這裏
            PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
}

這裏可以看到 spring已經獲取到了這個bean的所有依賴的實例,並將其註冊到 beanDefinition的PropertyValues中。最後調用了postProcessPropertyValues方法,完成最後的裝配工作。

 

 

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    //這裏獲取到bean 自動注入的元數據
    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;
}



private InjectionMetadata findAutowiringMetadata(Class<?> clazz) {
        // 先找緩存
        InjectionMetadata metadata = this.injectionMetadataCache.get(clazz);
        if (metadata == null) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(clazz);
                if (metadata == null) {
                    //緩存沒有,調用buildAutowiringMetadata方法構建
                    metadata = buildAutowiringMetadata(clazz);
                    this.injectionMetadataCache.put(clazz, metadata);
                }
            }
        }
        return metadata;
    }



private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {

    List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
        //這裏處理所有需要被自動注入的屬性
        ReflectionUtils.doWithLocalFields(targetClass, field -> {
            //獲取到所有要被自動注入的屬性
            MergedAnnotation<?> ann = findAutowiredAnnotation(field);
            if (ann != null) {
                //這裏排除靜態屬性
                if (Modifier.isStatic(field.getModifiers())) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Autowired annotation is not supported on static fields: " + field);
                    }
                    return;
                }
                boolean required = determineRequiredStatus(ann);
                //註冊
                currElements.add(new AutowiredFieldElement(field, required));
            }
        });

        //......省略了方法的自動注入

        elements.addAll(0, currElements);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);
    //將註冊好的InjectionElement集合添加到InjectionMetadata中。
    return InjectionMetadata.forElements(elements, clazz);
}

 這裏的重點就是調用了 findAutowiredAnnotation 方法,找到了所有需要被自動注入的屬性,並將其封裝在InjectionMetadata對象中返回,最終由InjectionMetadata 的 inject進行注入。

 

 

private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    MergedAnnotations annotations = MergedAnnotations.from(ao);
    //這裏匹配所有自動注入類型的註解
    for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
        MergedAnnotation<?> annotation = annotations.get(type);
        if (annotation.isPresent()) {
            return annotation;
        }
    }
    return null;
}

 

通過斷點可以看到,自動注入類型的註解 有兩個,分別是@Autowired和@value。也就是說,標註有這兩個註解的屬性就會被認爲是需要被自動注入的屬性,從而被返回。

到了這裏,bean的自動注入過程也就結束了。  

最後通過一個圖,我們看看整體的流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章