Spring源碼分析-BeanFactoryPostProcessors 應用之 PropertyPlaceholderConfigurer

BeanFactoryPostProcessors

介紹

BeanFactoryPostProcessors完整定義:java

/**
 * Allows for custom modification of an application context's bean definitions,
 * adapting the bean property values of the context's underlying bean factory.
 * @see BeanPostProcessor
 * @see PropertyResourceConfigurer
 */
public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

咱們知道spring最大優勢就是其可擴展性,BeanFactoryPostProcessor接口就是spring中提供給咱們用於擴展的一個地方。咱們看該接口上的javadoc其實很是的詳細,這也是咱們看spring源碼的一個技巧,就是看一個類是幹嗎的必定要先通讀其註釋。spring

結合接口上的註釋大體描述下BeanFactoryPostProcessor:
容許用戶經過修改applicationContext 中的bean定義(就是xml中定義的bean的信息即:BeanDefinition是和xml有一對一的配置,好比是不是單利,以及propert 屬性的賦值等)
來調整applicationContext中bean工廠中bean屬性值。

也就是說執行到BeanFactoryPostProcessor時所有的BeanDefinition定義已經加載好了可是bean實例尚未被建立,咱們能夠修補或者覆蓋bean屬性值。

咱們能夠看一下ApplicationContext中BeanFactoryPostProcessor的調用位置來印證是否如此app

下面是ApplicationContext核心代碼:ide

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            
            //獲取beanFactory實例
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        
            prepareBeanFactory(beanFactory);

            try {
             
                postProcessBeanFactory(beanFactory);

                //這裏正是咱們的BeanFactoryPostProcessor執行的位置
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //建立非懶加載的全部單例  這裏是真正建立bean實例的地方
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

通過源碼分析

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

這兩步咱們已經拿到了beanFactory實例,也就是每個bean對應的BeanDefinition已經加載好了。下面纔是執行invokeBeanFactoryPostProcessors(beanFactory),也就印證了咱們上面的結論。
下面咱們經過一個BeanFactoryPostProcessor的典型應用PropertyPlaceholderConfigurer來詳細講解BeanFactoryPostProcessor執行原理post

PropertyPlaceholderConfigurer

簡單使用的例子

PropertyPlaceholderConfigurer相信你們都使用過,咱們在配置bean的屬性可使用佔位符來賦值,而後經過調整properties文件中對應的屬性值來修改。看一個使用PropertyPlaceholderConfigurer簡單的例子:單元測試

public class Student {
    
        private String name;
    
        private Integer age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }

    <bean class="com.yalunwang.Student" id="student">
        <property name="name" value="${student.name}"></property>
        <property name="age" value="${student.age}"></property>
    </bean>

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:bean.properties"></property>
    </bean>

bean.properties配置文件:測試

student.name=anan
    student.age=2

單元測試:ui

@Test
    public void test_ioc_app(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-ioc.xml");

        Student student =(Student) ac.getBean("student");

        System.out.println("name: "+student.getName());
        System.out.println("age: "+student.getAge());
    }

輸出結果一切正常:this

name: anan
age: 2

源碼分析

先看一下PropertyPlaceholderConfigurer的類繼承圖:

能夠看到PropertyPlaceholderConfigurer實現了BeanFactoryPostProcessor和 PriorityOrdered。

咱們接着對上面的 invokeBeanFactoryPostProcessors(beanFactory)繼續進行分析:

/**
     * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
     * respecting explicit order if given.
     * 實例化並調用全部已註冊的BeanFactoryPostProcessor Bean,
     * 若是繼承了Order接口按順序執行
     * <p>Must be called before singleton instantiation.
     */
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<String>();
        //若是是beanFactory實現了BeanDefinitionRegistry
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
            List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                    new LinkedList<BeanDefinitionRegistryPostProcessor>();
            //遍歷硬編碼設置的beanFactory後置處理器          
            for (BeanFactoryPostProcessor postProcessor : getBeanFactoryPostProcessors()) {
                //若是是BeanDefinitionRegistryPostProcessor類型先執行postProcessBeanDefinitionRegistry方法再將其添加到registryPostProcessors集合中進行後續postProcessBeanFactory方法的執行
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryPostProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryPostProcessors.add(registryPostProcessor);
                }
                else {
                    //同理將正常的beanFactory後置處理器添加到regularPostProcessors集合中進行後續postProcessBeanFactory方法的執行
                    regularPostProcessors.add(postProcessor);
                }
            }
            //找出配置的BeanDefinitionRegistryPostProcessor後置處理器 
            Map<String, BeanDefinitionRegistryPostProcessor> beanMap =
                    beanFactory.getBeansOfType(BeanDefinitionRegistryPostProcessor.class, true, false);
            List<BeanDefinitionRegistryPostProcessor> registryPostProcessorBeans =
                    new ArrayList<BeanDefinitionRegistryPostProcessor>(beanMap.values());
            OrderComparator.sort(registryPostProcessorBeans);
            //執行BeanDefinitionRegistryPostProcessor後置處理器的postProcessBeanDefinitionRegistry方法
            for (BeanDefinitionRegistryPostProcessor postProcessor : registryPostProcessorBeans) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
            //執行上面添加的beanFactory後置處理器的集合裏的方法
            invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(registryPostProcessorBeans, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
            //處理後的添加到集合裏 防止後面重複執行
            processedBeans.addAll(beanMap.keySet());
        }
        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(getBeanFactoryPostProcessors(), beanFactory);
        }

    
        //獲取配置的BeanFactoryPostProcessor
        //如下按實現了 PriorityOrdered  Ordered 沒有繼承 三種進行優先級排序執行 
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
        
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        List<String> orderedPostProcessorNames = new ArrayList<String>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
        for (String ppName : postProcessorNames) {
            //這個就是上面記錄的若是已經處理了配置的BeanFactoryPostProcessors就跳過
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        OrderComparator.sort(priorityOrderedPostProcessors);
        //上面咱們說了PropertyPlaceholderConfigurer 實現了BeanFactoryPostProcessor和 PriorityOrdered,因此會在這一步執行調用
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        OrderComparator.sort(orderedPostProcessors);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    }

上面主要的執行邏輯我都添加了中文註釋方便你們理解。
總結一下改方法主要作的事情:

  1. 先判斷若是beanFactory是BeanDefinitionRegistry類型的話就添加對BeanDefinitionRegistryPostProcessor類型的調用,BeanDefinitionRegistryPostProcessor接口是BeanFactoryPostProcessor的子接口,BeanDefinitionRegistryPostProcessor的做用是方便咱們能夠手動註冊bean交給spring來管理,能夠經過擴展其惟一的方法(void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;) 來註冊bean到spring裏,這個不是本次分析的重點後面再舉例講解。
  2. 先對硬編碼配置的BeanFactoryPostProcessor進行處理 若是是BeanDefinitionRegistryPostProcessor類型會進行postProcessBeanDefinitionRegistry調用和postProcessBeanFactory調用,若是不是則只進行postProcessBeanFactory調用。
  3. 再對配置的BeanDefinitionRegistryPostProcessor進行處理(postProcessBeanDefinitionRegistry調用和postProcessBeanFactory調用)
  4. 最後對配置BeanFactoryPostProcessor的進行處理會按 PriorityOrdered/Ordered/沒有繼承任何排序接口 三種進行優先級排序執行postProcessBeanFactory調用。其中咱們的PropertyPlaceholderConfigurer 實現了BeanFactoryPostProcessor和 PriorityOrdered,因此會在這一步執行調用
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
  • ** 咱們繼續進行分析:**

invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

會執行PropertyPlaceholderConfigurer父類PropertyResourceConfigurer中的方法

/**
     * {@linkplain #mergeProperties Merge}, {@linkplain #convertProperties convert} and
     * {@linkplain #processProperties process} properties against the given bean factory.
     * @throws BeanInitializationException if any properties cannot be loaded
     */
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            Properties mergedProps = mergeProperties();

            // Convert the merged properties, if necessary.
            convertProperties(mergedProps);

            // Let the subclass process the properties.
            processProperties(beanFactory, mergedProps);
        }
        catch (IOException ex) {
            throw new BeanInitializationException("Could not load properties", ex);
        }
    }

mergeProperties()方法會先將 配置的properties加載到mergedProps裏
後面調用** processProperties(beanFactory, mergedProps)**;進行處理

  • processProperties(beanFactory, mergedProps)分析
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
            throws BeansException {

        StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);

        this.doProcessProperties(beanFactoryToProcess, valueResolver);
    }

這裏只有兩行代碼,第一行是建立StringValueResolver實例(用於替換佔位符的真正方法)
咱們跨過千山萬水終於要到立刻要進行佔位符替換了,繼續分析

protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            StringValueResolver valueResolver) {
       
        
        //將建立的valueResolver設置到BeanDefinitionVisitor裏 用於最終替換邏輯 (替換佔位符爲對應properties裏配置的值)
        BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
        //拿出ioc容器裏註冊的beans
        String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
        for (String curName : beanNames) {
            
            //排除掉當前beanName也就是 PropertyPlaceholderConfigurer Bean 且beanFactoryToProcess必須是當前容器
            if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
                //獲取一個bean對應的bean定義
                BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
                try {
                    //進行bean定義元數據的替換操做
                    visitor.visitBeanDefinition(bd);
                }
                catch (Exception ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage());
                }
            }
        }

        // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
        beanFactoryToProcess.resolveAliases(valueResolver);

        // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
        beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
    }

上面我已經使用中文註釋寫的很清楚了接着進行分析

  • visitor.visitBeanDefinition(bd);
public void visitBeanDefinition(BeanDefinition beanDefinition) {
        visitParentName(beanDefinition);
        visitBeanClassName(beanDefinition);
        visitFactoryBeanName(beanDefinition);
        visitFactoryMethodName(beanDefinition);
        visitScope(beanDefinition);
        visitPropertyValues(beanDefinition.getPropertyValues());
        ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
        visitIndexedArgumentValues(cas.getIndexedArgumentValues());
        visitGenericArgumentValues(cas.getGenericArgumentValues());
    }

這裏能夠對應 bean的parentName beanClassName property等進行替換操做咱們這裏只關注屬性的替換操做

  • visitPropertyValues(beanDefinition.getPropertyValues());
protected void visitPropertyValues(MutablePropertyValues pvs) {
        PropertyValue[] pvArray = pvs.getPropertyValues();
        for (PropertyValue pv : pvArray) {
            Object newVal = resolveValue(pv.getValue());
            if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {
                pvs.add(pv.getName(), newVal);
            }
        }
    }
  • Object newVal = resolveValue(pv.getValue());
@SuppressWarnings("rawtypes")
    protected Object resolveValue(Object value) {
        if (value instanceof BeanDefinition) {
            visitBeanDefinition((BeanDefinition) value);
        }
        else if (value instanceof BeanDefinitionHolder) {
            visitBeanDefinition(((BeanDefinitionHolder) value).getBeanDefinition());
        }
        else if (value instanceof RuntimeBeanReference) {
            RuntimeBeanReference ref = (RuntimeBeanReference) value;
            String newBeanName = resolveStringValue(ref.getBeanName());
            if (!newBeanName.equals(ref.getBeanName())) {
                return new RuntimeBeanReference(newBeanName);
            }
        }
        else if (value instanceof RuntimeBeanNameReference) {
            RuntimeBeanNameReference ref = (RuntimeBeanNameReference) value;
            String newBeanName = resolveStringValue(ref.getBeanName());
            if (!newBeanName.equals(ref.getBeanName())) {
                return new RuntimeBeanNameReference(newBeanName);
            }
        }
        else if (value instanceof Object[]) {
            visitArray((Object[]) value);
        }
        else if (value instanceof List) {
            visitList((List) value);
        }
        else if (value instanceof Set) {
            visitSet((Set) value);
        }
        else if (value instanceof Map) {
            visitMap((Map) value);
        }
        else if (value instanceof TypedStringValue) {
            TypedStringValue typedStringValue = (TypedStringValue) value;
            String stringValue = typedStringValue.getValue();
            if (stringValue != null) {
                String visitedString = resolveStringValue(stringValue);
                typedStringValue.setValue(visitedString);
            }
        }
        else if (value instanceof String) {
            return resolveStringValue((String) value);
        }
        return value;
    }

這裏有不少類型,是由於spring支持不少類型的配置好比property的值咱們能夠配置爲ref=xxxbean那麼value就是RuntimeBeanReference類型,
若是配置

<list>
                <value>343</value>
                <value>45</value>
            </list>

那麼value就是List類型等等。這裏咱們例子中配置的類型是TypedStringValue,那麼執行

else if (value instanceof TypedStringValue) {
            TypedStringValue typedStringValue = (TypedStringValue) value;
            //這裏拿到的值是原始的帶有佔位符的好比例子裏就是${student.name}、${student.age}這種
            String stringValue = typedStringValue.getValue();
            if (stringValue != null) {
                //這一步就是去進行替換
                String visitedString = resolveStringValue(stringValue);
                typedStringValue.setValue(visitedString);
            }
        }
  • String visitedString = resolveStringValue(stringValue);
/**
     * Resolve the given String value, for example parsing placeholders.
     * @param strVal the original String value
     * @return the resolved String value
     */
    protected String resolveStringValue(String strVal) {
        if (this.valueResolver == null) {
            throw new IllegalStateException("No StringValueResolver specified - pass a resolver " +
                    "object into the constructor or override the 'resolveStringValue' method");
        }
        //調用咱們以前傳進來的valueResolver也就是上面 (BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver); 這裏傳進來的) 進行替換操做
        String resolvedValue = this.valueResolver.resolveStringValue(strVal);
        // Return original String if not modified.
        return (strVal.equals(resolvedValue) ? strVal : resolvedValue);
    }

valueResolver其實就是PlaceholderResolvingStringValueResolver實例,它又委託PropertyPlaceholderHelper進行操做

也就是

/**
     * Replaces all placeholders of format {@code ${name}} with the value returned
     * from the supplied {@link PlaceholderResolver}.
     * @param value the value containing the placeholders to be replaced.
     * @param placeholderResolver the {@code PlaceholderResolver} to use for replacement.
     * @return the supplied value with placeholders replaced inline.
     */
    public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
        Assert.notNull(value, "Argument 'value' must not be null.");
        return parseStringValue(value, placeholderResolver, new HashSet<String>());
    }

    protected String parseStringValue(
            String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {

        StringBuilder buf = new StringBuilder(strVal);

        int startIndex = strVal.indexOf(this.placeholderPrefix);
        while (startIndex != -1) {
            int endIndex = findPlaceholderEndIndex(buf, startIndex);
            if (endIndex != -1) {
                //將ex. ${student.name} 轉成 student.name
                String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex);
                String originalPlaceholder = placeholder;
                if (!visitedPlaceholders.add(originalPlaceholder)) {
                    throw new IllegalArgumentException(
                            "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
                }
                // 遞歸調用直到沒有佔位符
                placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
                // 獲取properties配置文件對應的值  就是獲取student.name 對應在 properties裏的值
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);
                if (propVal == null && this.valueSeparator != null) {
                    int separatorIndex = placeholder.indexOf(this.valueSeparator);
                    if (separatorIndex != -1) {
                        String actualPlaceholder = placeholder.substring(0, separatorIndex);
                        String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
                        propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
                        if (propVal == null) {
                            propVal = defaultValue;
                        }
                    }
                }
                if (propVal != null) {
                    //再次遞歸調用 確保最後的值沒有佔位符
                    propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
                    //將原先的StringBuff的原始值替換爲拿到的值
                    buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Resolved placeholder '" + placeholder + "'");
                    }
                    //這裏由於已經替換成真正的值 拿不到佔位符(${)因此值就是-1 會跳出循環返回
                    startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length());
                }
                else if (this.ignoreUnresolvablePlaceholders) {
                    // Proceed with unprocessed value.
                    startIndex = buf.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
                }
                else {
                    throw new IllegalArgumentException("Could not resolve placeholder '" +
                            placeholder + "'" + " in string value \"" + strVal + "\"");
                }
                visitedPlaceholders.remove(originalPlaceholder);
            }
            else {
                startIndex = -1;
            }
        }

        return buf.toString();
    }

該方法是真正替換的操做所在,改方法已經添加中文註釋應該很好理解了,總結就是作了一下兩件事:
1.首先會將ex. ${student.name} 轉成 student.name
2.將student.name經過 tring propVal = placeholderResolver.resolvePlaceholder(placeholder);獲取真正的值而後返回。

protected String resolvePlaceholder(String placeholder, Properties props, int systemPropertiesMode) {
        String propVal = null;
        if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
            propVal = resolveSystemProperty(placeholder);
        }
        if (propVal == null) {
            propVal = resolvePlaceholder(placeholder, props);
        }
        if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
            propVal = resolveSystemProperty(placeholder);
        }
        return propVal;
    }

該方法就比較簡單了就是根據不一樣的模式作處理,systemPropertiesMode默認是SYSTEM_PROPERTIES_MODE_FALLBACK

  1. 若是systemPropertiesMode = SYSTEM_PROPERTIES_MODE_OVERRIDE 是指 系統配置文件優先級大於咱們的配置文件。
  2. 拿不到或者配置不等於SYSTEM_PROPERTIES_MODE_OVERRIDE 就去咱們配置文件裏進行獲取
  3. 若是還獲取不到且若是systemPropertiesMode=SYSTEM_PROPERTIES_MODE_FALLBACK就再嘗試去系統文件裏查找。

結論

通過以上各個步驟最終BeanDefinition裏的parentName beanClassName property中的佔位符都會被咱們propertis配置文件中對應的值所替換掉,這就爲後續實例化bean後作bean實例屬性填充時作好了準備。
咱們再進行 Student student =(Student) ac.getBean("student"); 時就能夠正常打印對應的值了。

看源碼的一點分享tip

  • 看源碼可能會比較枯燥,堅持很重要,若是看一遍是懵的那就是歇一歇再繼續多看幾遍這樣慢慢就會找到感受
  • 看的過程當中必定要寫例子進行調試,而後再繼續反覆看慢慢就會明白其中的含義
  • 看源碼能夠看某一個核心類的繼承圖,以及javadoc。還能夠嘗試畫出核心的時序圖,這些都能對咱們看懂源碼起到事半功倍的做用。

至此本篇源碼分析就結束了,後續繼續spring源碼分析的文章。加油!!!

相關文章
相關標籤/搜索