prepareBeanFactory方法源碼跟蹤

看這篇文章以前能夠先了解以前的跟蹤流程,https://www.jianshu.com/p/4934233f0eadhtml

代碼過寬,能夠shift + 鼠標滾輪 左右滑動查看java

AbstractApplicationContext類refresh()方法中的第三個調用方法prepareBeanFactory()的跟蹤。spring

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
        // Prepare the bean factory for use in this context.
        // 準備在上下文中bean factory的使用
        prepareBeanFactory(beanFactory);
        ···
 }

斷點進入跟蹤。express

此方法的實如今AbstractApplicationContext類中。緩存

prepareBeanFactory(零)

/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
*
* 配置工廠的標準上下文特徵,好比上下文的ClassLoader和post-processors
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    // Tell the internal bean factory to use the context's class loader etc.
    //告知內部的bean工廠,使用上下文的類加載器
    beanFactory.setBeanClassLoader(getClassLoader());
    
    //設置bean表達式解析器,
    //StandardBeanExpressionResolver內部expressionParser屬性默認SpelExpressionParser類型
    //spel = spring el表達式
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    
    //將ResourceEditorRegistrar實例添加到工廠的propertyEditorRegistrars屬性中,
    //propertyEditorRegistrars是一個LinkedHashSet,裏面的元素將會應用到工廠bean中
    //ResourceEditorRegistrar持有上下文和environment的引用
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    // 使用上下文回調配置bean 工廠
    //在工廠的beanPostProcessor屬性中添加處理器,beanPostProcessor是一個ArrayList
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    //在工廠的ignoredDependencyInterfaces屬性中添加Aware系列接口,
    //ignoredDependencyInterfaces是一個HashSet
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    
    // 在普通的工廠中,BeanFactory接口並無按照resolvable類型進行註冊
    // MessageSource被註冊成一個Bean(並被自動注入)
    
    //BeanFactory.class爲key,beanFactory爲value放入到了beanFactory的resolvableDependencies屬性中
    //resolvableDependencies是一個ConcurrentHashMap,映射依賴類型和對應的被注入的value
    //這樣的話BeanFactory/ApplicationContext雖然沒有以bean的方式被定義在工廠中,
    //可是也可以支持自動注入,由於他處於resolvableDependencies屬性中
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    
    //再將上下文的一些接口與上下文自己作映射,一一放入到resolvableDependencies中
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 檢測LoadTimeWeaver,若是有就準備織入
    //1.跟蹤進入,淺看下containsBean方法
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        
        //若是有LoadTimeWeaver,加入bean後處理器
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        
        // Set a temporary ClassLoader for type matching.
        // 爲匹配類型設置一個臨時的ClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    // 註冊默認的environment beans
    
    // 判斷目前這個bean工廠中是否包含指定name的bean,忽略父工廠
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        
        //雖然XmlWebApplicationContext中持有默認實現的StandardServletEnvironment
        //可是沒有註冊到beanFactory中,經過getEnvironment方法拿到持有的引用
        //2.註冊environment單例
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        
        //註冊systemProperties單例
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        
        //註冊systemEnvironment單例
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

1.containsBean

跟蹤標記爲1的方法app

此方法的實如今AbstractBeanFactory類中編輯器

//1.跟蹤看下containsBean方法
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)

    
/**
* Does this bean factory contain a bean definition or externally registered singleton
* instance with the given name?
* <p>If the given name is an alias, it will be translated back to the corresponding
* canonical bean name.
* <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
* be found in this factory instance.
* <p>If a bean definition or singleton instance matching the given name is found,
* this method will return {@code true} whether the named bean definition is concrete
* or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
* return value from this method does not necessarily indicate that {@link #getBean}
* will be able to obtain an instance for the same name.
*
* bean工廠是否包含一個給定name的bean definition,或者外部被註冊的單例bean?
* 若是name是一個別名,會被轉換成對應的beanName
* 若是工廠是有層級的,那麼當工廠實例中找不到這個bean時,就會去父工廠中查找
* 若是找到匹配name的bean definition或者單例,那麼這個方法會返回true
* 無論這個bean definition是具體的仍是抽象的,提早加載仍是懶加載,是否在範圍中。
* 所以,注意從這個方法中返回的true值並不表明從getBean方法中可以獲取一個同名稱的實例
*/
@Override
public boolean containsBean(String name) {
    
    //1.1對name進行必要的轉換
    String beanName = transformedBeanName(name);
    
    //singletonObjects或者beanDefinitionMap中已註冊beanName則進入條件
    //說明該beanName有對應的bean definition,或者單例bean
    if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
        
        //name開頭不爲&返回true,若是帶了&可是是FactoryBean也返回true
        //要注意下FactoryBean和BeanFactory的區別,能夠看下文參考連接
        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
    }
    
    // Not found -> check parent.
    // 若是沒有找到對應beanName的bean或者bean definition,那麼從父工廠查找
    BeanFactory parentBeanFactory = getParentBeanFactory();
    
    return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}

1.1 transformedBeanName

跟蹤標記爲1.1的方法ide

此方法的實如今AbstractBeanFactory類中post

//1.1對name進行必要的轉換
String beanName = transformedBeanName(name);

/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
*
* 返回bean name,剝離factory dereference 前綴,並將別名解析爲bean name
*/
protected String transformedBeanName(String name) {
    
    //總的來講,若是name表明factory,那麼name前就帶有&前綴,去掉此前綴
    //若是這個name是beanName,則直接返回,若是name是alias,在aliasMap中查找對應的beanName,再返回
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

//先看下transformedBeanName方法的實現
//進入BeanFactoryUtils類中
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
*
* 返回真實的beanName,剝離工廠前綴(若是有的話,也剝離重複的工廠前綴)
*/
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    String beanName = name;
    //FACTORY_BEAN_PREFIX常量爲:&
    while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
    }
    return beanName;
}


//再進入canonicalName方法查看
//此方法在SimpleAliasRegistry中實現,被默認bean工廠間接繼承
/**
* Determine the raw name, resolving aliases to canonical names.
*
* 肯定原生的name,將別名解析爲BeanName
*/
public String canonicalName(String name) {
    String canonicalName = name;
    
    // Handle aliasing...
    // 處理別名
    String resolvedName;
    do {
        
        //拿到canonicalName對應的實際名稱
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    
    //只有當canonicalName在aliasMap中對應的value爲null時,才跳出循環
    //這時候說明canonicalName已經不做爲其餘任何BeanName的別名,排除了間接引用
    //canonicalName就爲真正的beanName
    while (resolvedName != null);
    return canonicalName;
}

2.registerSingleton

跟蹤標記爲2的方法this

此方法的實如今DefaultListableBeanFactory類中

//2.註冊environment單例
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());


@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    
    //2.1調用父類方法,註冊單例
    super.registerSingleton(beanName, singletonObject);

    //AbstractBeanFactory類中有個集合屬性alreadyCreated
    //裏面保存在至少被建立過一次的beanName
    //若是這個集合中存在beanName,那麼說明已經進入了bean建立階段
    if (hasBeanCreationStarted()) {
        
        // Cannot modify startup-time collection elements anymore (for stable iteration)
        // 沒法再修改啓動時集合元素(爲了穩定迭代)
        synchronized (this.beanDefinitionMap) {
            
            //beanName不在beanDefinitionMap中,說明是手動註冊
            if (!this.beanDefinitionMap.containsKey(beanName)) {
                Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames.size() + 1);
                updatedSingletons.addAll(this.manualSingletonNames);
                updatedSingletons.add(beanName);
                this.manualSingletonNames = updatedSingletons;
            }
        }
    }
    else {
        
        // Still in startup registration phase
        // 仍然處於啓動註冊階段
        if (!this.beanDefinitionMap.containsKey(beanName)) {
            
            //屬於手動註冊狀況
            //environment屬於手動註冊單例
            this.manualSingletonNames.add(beanName);
        }
    }
    
    //進入這個方法查看
    clearByTypeCache();
}


/**
* Remove any assumptions about by-type mappings.
*
* 刪除按照類型映射有關的任何假設
*/
private void clearByTypeCache() {
    
    //allBeanNamesByType是單例和非單例beanName的映射,key是依賴類型
    this.allBeanNamesByType.clear();
    
    //僅單例beanName的映射,key是依賴類型
    this.singletonBeanNamesByType.clear();
}

2.1 registerSingleton

跟蹤標記爲2.1的方法

此方法的實如今DefaultSingletonBeanRegistry類中

//2.1調用父類方法,註冊單例
super.registerSingleton(beanName, singletonObject);


/**
* Register the given existing object as singleton in the bean registry,
* under the given bean name.
* <p>The given instance is supposed to be fully initialized; the registry
* will not perform any initialization callbacks (in particular, it won't
* call InitializingBean's {@code afterPropertiesSet} method).
* The given instance will not receive any destruction callbacks
* (like DisposableBean's {@code destroy} method) either.
* <p>When running within a full BeanFactory: <b>Register a bean definition
* instead of an existing instance if your bean is supposed to receive
* initialization and/or destruction callbacks.</b>
* <p>Typically invoked during registry configuration, but can also be used
* for runtime registration of singletons. As a consequence, a registry
* implementation should synchronize singleton access; it will have to do
* this anyway if it supports a BeanFactory's lazy initialization of singletons.
* 
* 在給定的bean name下,將存在的對象做爲單例註冊在工廠中
* 給定的實例應該是徹底初始化;工廠不執行任何初始化回調(特別是,他不會調用InitializingBean的
* afterPropertiesSet方法)
* 給定的實例也不接收任何銷燬回調(像DisposableBean的destroy方法)
* 當在完整的BeanFactory運行時:
* 若是你的bean須要接收初始化或者銷燬的回調,註冊一個bean definition替代一個存在的實例
* 一般此方法在工廠配置時被調用,也能在運行時單例註冊時被調用。
* 做爲結果,工廠的實現應該同步單例的訪問;若是支持BeanFactory的單例的延遲初始化就不得不這樣作
*/
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {
        Object oldObject = this.singletonObjects.get(beanName);
        
        //不能註冊兩次
        if (oldObject != null) {
            throw new IllegalStateException("Could not register object [" + singletonObject +
                                            "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
        }
        
        //進入這個方法
        addSingleton(beanName, singletonObject);
    }
}

/**
* Add the given singleton object to the singleton cache of this factory.
* <p>To be called for eager registration of singletons.
*
* 添加給定單例對象到工廠的單例緩存中
* 用來被提前註冊的單例調用
*/
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        
        //singletonObjects是一個ConcurrentHashMap
        //用來緩存單例對象
        this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
        
        //singletonFactories是一個HashMap
        //裏面緩存着單例工廠
        this.singletonFactories.remove(beanName);
        
        //早期單例對象
        //earlySingletonObjects是一個HashMap
        this.earlySingletonObjects.remove(beanName);
        
        //registeredSingletons是一個LinkedHashSet
        //被註冊單例的集合,以註冊的順序包含着bean name
        this.registeredSingletons.add(beanName);
    }
}

這樣,整個prepareBeanFactory方法也就跟蹤完畢了。

接下來跟蹤postProcessBeanFactory方法:
https://www.jianshu.com/p/c05aea93b939

參考

BeanFactory和FactoryBean的區別:https://www.cnblogs.com/aspirant/p/9082858.html

總結

  • 爲工廠設置類的加載器、表達式解析器、屬性編輯器註冊器等
  • 爲工廠添加後處理器、要忽略的依賴接口
  • 在工廠中註冊可解析的依賴
  • 在工廠中提早註冊一些單例Bean
相關文章
相關標籤/搜索