看這篇文章以前能夠先了解以前的跟蹤流程,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類中。緩存
/** * 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的方法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的方法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的方法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的方法
此方法的實如今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