寫這篇博文的主要目的以下:java
看看下面這張圖(摘自《Spring技術內幕》),IoC容器的設計分爲兩條線,react
爲何這樣要分兩條線呢,主要是將容器和上下文區分開來。由於在在Spring項目中,上下文對容器不只是擴展的關係,更重要的是持有的關係,上下文是以屬性的形式持有了容器,開發者能夠經過上下文對象獲取到容器。筆者十分傾向於將兩者分開來理解。固然也能夠將應用上下文理解成容器的高級表現形式。web
BeanFactory定義了IoC容器的基本規範,包括getBean()按類型和按名稱的獲取Bean的方法。spring
HierarchicalBeanFactory 在BeanFactory的基礎上增長了getParentBeanFactory()方法,使BeanFactory具有了雙親IoC容器管理的功能。緩存
ConfigurableBeanFactory接口提供了配置BeanFactory的各類方法。好比setParentBeanFactory()方法,配置上面提到的雙親IoC容器,addBeanPostProcessor()方法,配置Bean後置處理器等。tomcat
到這裏先埋個包袱:到ConfigurableBeanFactory接口爲止,IoC容器尚未具有做爲「容器」最基本的功能,那就是能裝東西。服務器
上面說了應用上下文是IoC容器的高級表現形式,ListableBeanFactory具有了操做BeanDefinition 的能力,好比getBeanDefinitionCount()方法,能夠獲取Bean的總數等。數據結構
ApplicationContext 類那就厲害了,以下代碼所示,實現了一大堆接口app
1 public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, 2 MessageSource, ApplicationEventPublisher, ResourcePatternResolver
WebApplicationContext擴展了對web應用的支持。框架
ConfigurableApplicationContext就更重要了,看過Spring源碼的都知道一個重要的方法叫refresh,沒錯就是在這個接口中定義的。最重要的是擴展了配置上下文的功能,和控制上下文生命週期的能力等等。
首先證實一點,爲何說DefaultListableBeanFactory類是具體的實現類呢?
隨便啓動一個SpringBoot項目找到第25行代碼(在SpringBoot的啓動流程系列博文中有介紹)
1 public ConfigurableApplicationContext run(String... args) { 2 //記錄程序運行時間 3 StopWatch stopWatch = new StopWatch(); 4 stopWatch.start(); 5 // ConfigurableApplicationContext Spring 的上下文 6 ConfigurableApplicationContext context = null; 7 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); 8 configureHeadlessProperty(); 9 //從META-INF/spring.factories中獲取監聽器 10 //一、獲取並啓動監聽器 11 SpringApplicationRunListeners listeners = getRunListeners(args); 12 listeners.starting(); 13 try { 14 ApplicationArguments applicationArguments = new DefaultApplicationArguments( 15 args); 16 //二、構造容器環境 17 ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); 18 //處理須要忽略的Bean 19 configureIgnoreBeanInfo(environment); 20 //打印banner 21 Banner printedBanner = printBanner(environment); 22 ///三、初始化容器 23 context = createApplicationContext(); 24 //實例化SpringBootExceptionReporter.class,用來支持報告關於啓動的錯誤 25 exceptionReporters = getSpringFactoriesInstances( 26 SpringBootExceptionReporter.class, 27 new Class[]{ConfigurableApplicationContext.class}, context); 28 //四、刷新容器前的準備階段 29 prepareContext(context, environment, listeners, applicationArguments, printedBanner); 30 //五、刷新容器 31 refreshContext(context); 32 //刷新容器後的擴展接口 33 afterRefresh(context, applicationArguments); 34 stopWatch.stop(); 35 if (this.logStartupInfo) { 36 new StartupInfoLogger(this.mainApplicationClass) 37 .logStarted(getApplicationLog(), stopWatch); 38 } 39 listeners.started(context); 40 callRunners(context, applicationArguments); 41 } catch (Throwable ex) { 42 handleRunFailure(context, ex, exceptionReporters, listeners); 43 throw new IllegalStateException(ex); 44 } 45 46 try { 47 listeners.running(context); 48 } catch (Throwable ex) { 49 handleRunFailure(context, ex, exceptionReporters, null); 50 throw new IllegalStateException(ex); 51 } 52 return context; 53 }
debug
如2標註點所示IoC容器的真實面孔就是這個DefaultListableBeanFactory類了。固然他還有一個子類XmlBeanFactory,不過都已經被標註爲棄用了(@Deprecated)在《Spring技術內幕》這本書裏面也是着重的講的這個類,可能當時做者是以SpringMVC項目來說解的吧。XmlBeanFactory顧名思義就是提供了對xml配置方式的支持。呃。。。又勾起了用SpringMVC的痛苦回憶。
言歸正傳,
以下圖,看看他的繼承關係
章節二中提到了不少的IoC容器系列,這樣總結一下吧,俗話說一流企業作標準,二流企業作產品,章節二中的那一坨就是IoC容器的實現標準,本章節咱們要總結的類DefaultListableBeanFactory就是IoC容器的具體產品。
看見上圖中那一堆接口和類是否是有點懵,不要緊,我們慢慢梳理一下。
這條線路在上一章節中已經梳理過了。只是多出了ConfigurableListableBeanFactory接口,ConfigurableListableBeanFactory接口主要是增長指定忽略類型和接口等
這條設計路線乍一看仍是挺複雜的,的確是這樣。
1, BeanFactory ==> AutowireCapableBeanFactory ==> AbstractAutowireCapableBeanFactory ==> DefaultListableBeanFactory
在這條線路中,AutowireCapableBeanFactory接口定義了自動注入bean(autowireBean()),建立bean(createBean()),初始化bean(initializeBean())方法等。那麼真正實現這些方法的類即是AbstractAutowireCapableBeanFactory。
AbstractAutowireCapableBeanFactory抽象類中實現了AutowireCapableBeanFactory接口定義的方法。在此基礎上經過繼承AbstractBeanFactory具有了操做Bean的能力。
2, SingletonBeanRegistry ==> DefaultSingletonBeanRegistry ==> FactoryBeanRegistrySupport ==> AbstractBeanFactory ==> AutowireCapableBeanFactory ==> DefaultListableBeanFactory
這條關係鏈有點長,在這條鏈中咱們要關心的是SingletonBeanRegistry接口,顧名思義,這個接口是單例Bean的註冊接口。固然也不止註冊這麼簡單。以下圖中所示,除了註冊單例以外,還定義獲取單例的方法。
注意:爲何只有singleton的註冊中心,而沒有prototype類型的Bean的註冊中心呢?由於單例Bean(singleton)是Spring幫咱們建立的並維護的,原型Bean(prototype)是每次獲取都會建立出來一個實例。本質是不一樣的。
3, AliasRegistry ==> SimpleAliasRegistry ==> DefaultSingletonBeanRegistry ==> FactoryBeanRegistrySupport ==> AbstractBeanFactory ==> AutowireCapableBeanFactory ==> DefaultListableBeanFactory
這條路線呢,主要是提供管理別稱的能力。由於不是重點,在此就不詳細分析了。
4, AliasRegistry ==> BeanDefinitionRegistry ==> DefaultListableBeanFactory
BeanDefinitionRegistry接口要重點說一下,該接口是BeanDefinition的註冊中心。使DefaultListableBeanFactory具有操做BeanDefinition的能力。看一下它有什麼方法。
包括了註冊,刪除,獲取BeanDefinition的方法。固然這只是個接口,這些方法的具體實如今DefaultListableBeanFactory中。
如上圖所示,AbstractBeanFactory中實現了BeanFactory中定義的幾個重要的方法。經常使用的註解 @Autowired @Resource(name = "xxx") 你們都知道一個是按類查找,一個是按名獲取。具體實現這兩個註解的方法就是上圖中圈出來的幾個方法。幾個getBean()方法最終都進入了doGetBean()方法。doGetBean()方法是實際得到Bean的地方,也是觸發依賴注入發生的地方。在SpringBoot啓動流程總會對這個方法進行詳細的介紹。
AbstractBeanFactory中實現了getBean()方法,AbstractAutowireCapableBeanFactory中實現了Bean的建立方法。
當咱們須要定義一個Bean一般會有這樣寫 @Bean(name = "test", initMethod = "init", destroyMethod = "destroy") 。AbstractAutowireCapableBeanFactory中完成了一個Bean從 create(createBean()) ==> createInstance(createBeanInstance()) ==> init(invokeInitMethods()) 的全部工做。因此這個抽象類的做用不言而喻。具體的建立過程,會在SpringBoot的啓動流程中詳細介紹。
其實咱們常常說的Spring 容器,這個容器其實更多的是BeanFactory所表明的意義:Bean生產工廠。是滴,一般咱們理解的容器應該是能裝東西的,可是spring 容器不是表明表明水桶同樣的東西,而是像富士康同樣,生產東西的地方。好比咱們須要一個Bean,咱們只須要告訴spring,spring就會給咱們。因此到目前爲止咱們尚未看到IoC做爲「容器」的能力。以上言論純屬本身理解,不喜勿噴。
DefaultSingletonBeanRegistry屬性先貼出來
1 public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 2 /** 3 * Cache of singleton objects: bean name --> bean instance 4 * 緩存 單例對象 5 */ 6 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);//好習慣,建立ConcurrentHashMap,指定初始化因子,縱觀Spring源碼,建立HashMap,都有初始化因子。get 7 8 /** 9 * Cache of singleton factories: bean name --> ObjectFactory 10 * 緩存 單例工廠 11 */ 12 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 13 14 /** 15 * Cache of early singleton objects: bean name --> bean instance 16 * 緩存 提早暴露的對象 17 */ 18 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); 19 20 /** 21 * Set of registered singletons, containing the bean names in registration order 22 * 已經註冊的單例對象集合,按照註冊順序排序的,而且是不可重複的。 23 */ 24 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); 25 26 /** 27 * Names of beans that are currently in creation 28 * 29 */ 30 private final Set<String> singletonsCurrentlyInCreation = 31 Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 32 33 /** 34 * Names of beans currently excluded from in creation checks 35 */ 36 private final Set<String> inCreationCheckExclusions = 37 Collections.newSetFromMap(new ConcurrentHashMap<>(16)); 38 39 /** 40 * List of suppressed Exceptions, available for associating related causes 41 */ 42 @Nullable 43 private Set<Exception> suppressedExceptions; 44 45 /** 46 * Flag that indicates whether we're currently within destroySingletons 47 */ 48 private boolean singletonsCurrentlyInDestruction = false; 49 50 /** 51 * Disposable bean instances: bean name --> disposable instance 52 * spring是做爲一個註冊中心的樣子,在容器shutdown的時候,直接從這裏面找到須要執行destory鉤子的Bean 53 */ 54 private final Map<String, Object> disposableBeans = new LinkedHashMap<>(); 55 56 /** 57 * Map between containing bean names: bean name --> Set of bean names that the bean contains 58 * 名稱爲name的bean,所持有的beans 的映射關係 59 */ 60 private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16); 61 62 /** 63 * Map between dependent bean names: bean name --> Set of dependent bean names 64 * 名稱爲name的bean與其所依賴的bean的映射關係 65 */ 66 private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); 67 68 /** 69 * Map between depending bean names: bean name --> Set of bean names for the bean's dependencies 70 */ 71 private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64); 72 }
屬性singletonObjects ,沒錯,就是這個東東,最終存儲單例(singleton)Bean的地方,在SpringBoot啓動流程中,會詳細介紹存取的過程。上面說了原型(prototype)Bean是不須要緩存的,不解釋了。到這裏咱們初步看到了IoC做爲「容器」該有的樣子。
DefaultSingletonBeanRegistry上面提到的SingletonBeanRegistry接口的相關方法,而且增長了不少對單例的操做的方法。
上面咱們從IoC容器的宏觀設計角度闡述了DefaultListableBeanFactory做爲IoC容器的具體實現的設計思想。在這裏來分析一下這個類自己的設計。
首先看看該類的屬性
1 public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory 2 implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { 3 /** 4 * Map from serialized id to factory instance 5 * 緩存 序列化ID到 DefaultListableBeanFactory 實例的映射 6 */ 7 private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories = 8 new ConcurrentHashMap<>(8); 9 10 /** 11 * Optional id for this factory, for serialization purposes 12 */ 13 @Nullable 14 private String serializationId; 15 16 /** 17 * Whether to allow re-registration of a different definition with the same name 18 */ 19 private boolean allowBeanDefinitionOverriding = true; 20 21 /** 22 * Whether to allow eager class loading even for lazy-init beans 23 */ 24 private boolean allowEagerClassLoading = true; 25 26 /** 27 * Optional OrderComparator for dependency Lists and arrays 28 */ 29 @Nullable 30 private Comparator<Object> dependencyComparator; 31 32 /** 33 * Resolver to use for checking if a bean definition is an autowire candidate 34 * 被用來解決去校驗一個BeanDefinition是否是自動裝載的候選人 35 */ 36 private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); 37 38 /** 39 * Map from dependency type to corresponding autowired value 40 * 緩存 類型對應的自動裝載的Bean 41 */ 42 private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16); 43 44 /** 45 * Map of bean definition objects, keyed by bean name 46 * 緩存 beanName到BeanDefinition的映射關係 47 */ 48 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); 49 50 /** 51 * Map of singleton and non-singleton bean names, keyed by dependency type 52 * 緩存 類型 和 beanName的映射關係 53 */ 54 private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64); 55 56 /** 57 * Map of singleton-only bean names, keyed by dependency type 58 * 緩存 類型 和 單例Bean names的映射 59 */ 60 private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64); 61 62 /** 63 * List of bean definition names, in registration order 64 * 緩存 beanDefinition name的list 65 */ 66 private volatile List<String> beanDefinitionNames = new ArrayList<>(256); 67 68 /** 69 * List of names of manually registered singletons, in registration order 70 */ 71 private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16); 72 73 /** 74 * Cached array of bean definition names in case of frozen configuration 75 */ 76 @Nullable 77 private volatile String[] frozenBeanDefinitionNames; 78 79 /** 80 * Whether bean definition metadata may be cached for all beans 81 */ 82 private volatile boolean configurationFrozen = false; 83 }
在Spring中,其實是把DefaultListableBeanFactory做爲一個默認的功能完整的IoC容器來使用。 DefaultListableBeanFactory做爲一個功能完整的容器具有了除以上父類所具備功能外,還加入了對BeanDefinition的管理和維護。從上面的代碼能夠看到一個重要的屬性:beanDefinitionMap。beanDefinitionMap緩存了Bean name到 BeanDefinition的映射。到這裏是否是發現了IoC容器另一個做爲「容器」的能力。在個人理解範圍內,IoC容器做爲「容器」真正裝的兩個最總要的能力算是總結完了,一個是裝單例(Singleton)Bean,一個是裝BeanDefinition。
Spring經過定義BeanDefinition來管理基於Spring的應用中的各類對象以及他們之間的相互依賴關係。BeanDefinition抽象了咱們對Bean的定義,是讓容器起做用的主要數據類型。我麼都知道在計算機世界裏,全部的功能都是創建在經過數據對現實進行抽象的基礎上的。IoC容器是用來管理對象依賴關係的,對IoC容器來講,BeanDefinition就是對依賴反轉模式中管理的對象依賴關係的數據抽象,也是容器實現依賴反轉功能的核心數據結構,依賴反轉功能都是圍繞對這個BeanDefinition的處理來完成的。這些BeanDefinition就像是容器裏裝的水,有了這些基本數據,容器才能發揮做用。簡單一句話來講,BeanDefinition就是Bean的元數據,BeanDefinition存放了對Bean的基本描述,包括Bean擁有什麼屬性,方法,Bean的位置等等Bean的各類信息。IoC容器能夠經過BeanDefinition生成Bean。
BeanDefinition究竟長什麼樣呢?
在同第三章debug的地方同樣,點開beanFactory,而後查看beanDefinitionMap屬性。
OK,BeanDefinition就是長這樣了。具體怎麼經過它生成Bean,在SpringBoot啓動流程中會詳細介紹。
在SpringBoot工程中,應用類型分爲三種,以下代碼所示。
1 public enum WebApplicationType { 2 /** 3 * 應用程序不是web應用,也不該該用web服務器去啓動 4 */ 5 NONE, 6 /** 7 * 應用程序應做爲基於servlet的web應用程序運行,並應啓動嵌入式servlet web(tomcat)服務器。 8 */ 9 SERVLET, 10 /** 11 * 應用程序應做爲 reactive web應用程序運行,並應啓動嵌入式 reactive web服務器。 12 */ 13 REACTIVE 14 }
對應三種應用類型,SpringBoot項目有三種對應的應用上下文,咱們以web工程爲例,即其上下文爲AnnotationConfigServletWebServerApplicationContext
1 public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot." 2 + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext"; 3 public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework." 4 + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"; 5 public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." 6 + "annotation.AnnotationConfigApplicationContext"; 7 8 protected ConfigurableApplicationContext createApplicationContext() { 9 Class<?> contextClass = this.applicationContextClass; 10 if (contextClass == null) { 11 try { 12 switch (this.webApplicationType) { 13 case SERVLET: 14 contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS); 15 break; 16 case REACTIVE: 17 contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); 18 break; 19 default: 20 contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); 21 } 22 } catch (ClassNotFoundException ex) { 23 throw new IllegalStateException( 24 "Unable create a default ApplicationContext, " 25 + "please specify an ApplicationContextClass", 26 ex); 27 } 28 } 29 return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); 30 }
咱們先看一下AnnotationConfigServletWebServerApplicationContext的設計。
在2.2中已經介紹了ApplicationContext的設計
關於AnnotationConfigServletWebServerApplicationContext詳細的設計路線在這裏就不像DefaultListableBeanFactory容器那麼詳細的去講解了。在第二章說過,應用上下文能夠理解成IoC容器的高級表現形式,拿上圖和DefaultListableBeanFactory的繼承關係圖,不難發現,應用上下文確實是在IoC容器的基礎上豐富了一些高級功能。在第二章中,咱們還說過應用上下文對IoC容器是持有的關係。繼續看第二章debug的截圖,context就是AnnotationConfigServletWebServerApplicationContext的神祕面孔,他的一個屬性beanFactory就是IoC容器(DefaultListableBeanFactory)。因此他們之間是持有,和擴展的關係。
接下來看GenericApplicationContext類
1 public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { 2 private final DefaultListableBeanFactory beanFactory; 3 ... 4 }
第一行赫然定義了beanFactory屬性,正是DefaultListableBeanFactory對象。
關於上下文還有另一個最重要的方法refresh,上文中說道該方法是在ConfigurableApplicationContext接口中定義的,那麼在哪實現的該方法呢?
看AbstractApplicationContext類。
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 //刷新上下文環境 6 prepareRefresh(); 7 8 // Tell the subclass to refresh the internal bean factory. 9 //這裏是在子類中啓動 refreshBeanFactory() 的地方 10 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 11 12 // Prepare the bean factory for use in this context. 13 //準備bean工廠,以便在此上下文中使用 14 prepareBeanFactory(beanFactory); 15 16 try { 17 // Allows post-processing of the bean factory in context subclasses. 18 //設置 beanFactory 的後置處理 19 postProcessBeanFactory(beanFactory); 20 21 // Invoke factory processors registered as beans in the context. 22 //調用 BeanFactory 的後處理器,這些處理器是在Bean 定義中向容器註冊的 23 invokeBeanFactoryPostProcessors(beanFactory); 24 25 // Register bean processors that intercept bean creation. 26 //註冊Bean的後處理器,在Bean建立過程當中調用 27 registerBeanPostProcessors(beanFactory); 28 29 // Initialize message source for this context. 30 //對上下文中的消息源進行初始化 31 initMessageSource(); 32 33 // Initialize event multicaster for this context. 34 //初始化上下文中的事件機制 35 initApplicationEventMulticaster(); 36 37 // Initialize other special beans in specific context subclasses. 38 //初始化其餘特殊的Bean 39 onRefresh(); 40 41 // Check for listener beans and register them. 42 //檢查監聽Bean而且將這些監聽Bean向容器註冊 43 registerListeners(); 44 45 // Instantiate all remaining (non-lazy-init) singletons. 46 //實例化全部的(non-lazy-init)單件 47 finishBeanFactoryInitialization(beanFactory); 48 49 // Last step: publish corresponding event. 50 //發佈容器事件,結束Refresh過程 51 finishRefresh(); 52 } catch (BeansException ex) { 53 if (logger.isWarnEnabled()) { 54 logger.warn("Exception encountered during context initialization - " + 55 "cancelling refresh attempt: " + ex); 56 } 57 58 // Destroy already created singletons to avoid dangling resources. 59 destroyBeans(); 60 61 // Reset 'active' flag. 62 cancelRefresh(ex); 63 64 // Propagate exception to caller. 65 throw ex; 66 } finally { 67 // Reset common introspection caches in Spring's core, since we 68 // might not ever need metadata for singleton beans anymore... 69 resetCommonCaches(); 70 } 71 } 72 }
OK,應用上下文就介紹到這裏。
在這裏咱們先口述一下IoC容器的初始化過程吧,源碼分析,請移步SpringBoot啓動流程分析。
簡單來講IoC容器的初始化過程是由前面介紹的refresh()方法啓動的,這個方法標誌着IoC容器的正式啓動。具體來講,這個啓動包括三個過程
1 BeanDefinition的Resource定位 2 BeanDefinition的載入 3 向IoC容器註冊BeanDefinition
一、第一個過程:Resource定位
這個定位指的是BeanDefinition的資源定位,它由ResourceLoader經過統一的Resource接口完成,這個Resource對各類形式的BeanDefinition的使用都提供了統一接口。對於這些BeanDefinition的存在形式,能夠是經過像SpringMVC中的xml定義的Bean,也能夠是像在類路徑中的Bean定義信息,好比使用@Component等註解定義的。這個過程相似於容器尋找數據的過程,就像用水桶裝水先要把水找到同樣。
結合SpringBoot說一下這個過程,對於SpringBoot,咱們都知道他的包掃描是從主類所在的包開始掃描的,那這個定位的過程在SpringBoot中具體是這樣的,在refresh容器以前(prepareContext()方法中),會先將主類解析成BeanDefinition,而後在refresh方法中而且是掃描Bean以前,解析主類的BeanDefinition獲取basePackage的路徑。這樣就完成了定位的過程。(先不討論SpringBoot中指定掃描包路徑和自動裝配)
二、第二個過程:BeanDefinition的載入
這個載入過程是把用戶定義好的Bean表示成IoC容器內部的數據結構,而這個容器內部的數據結構就是BeanDefinition。
在SpringBoot中,上面咱們說到經過主類找到了basePackage,SpringBoot會將該路徑拼接成:classpath*:org/springframework/boot/demo/**/*.class這樣的形式,而後一個叫作PathMatchingResourcePatternResolver的類會將該路徑下全部的.class文件都加載進來,而後遍歷判斷是否是有@Component註解,若是有的話,就是咱們要裝載的BeanDefinition。大體過程就是這樣的了。
注意:@Configuration,@Controller,@Service等註解底層都是@Component註解,只不過包裝了一層罷了。
三、第三個過程:註冊BeanDefinition
這個過程經過調用上文提到的BeanDefinitionRegister接口的實現來完成。這個註冊過程把載入過程當中解析獲得的BeanDefinition向IoC容器進行註冊。經過上文的分析,咱們能夠看到,在IoC容器中將BeanDefinition注入到一個ConcurrentHashMap中,IoC容器就是經過這個HashMap來持有這些BeanDefinition數據的。好比DefaultListableBeanFactory 中的beanDefinitionMap屬性。
上面對IoC容器的初始化過程進行了詳細的介紹,這個過程完成的主要的工做是在IoC容器中創建BeanDefinition數據映射。在此過程當中並無看到IoC容器對Bean的依賴關係進行注入。依賴注入是Spring實現「控制反轉」的重要一環。Spring將依賴關係交給IoC容器來完成。
依賴控制反轉的實現有不少種方式。在Spring中,IoC容器是實現這個模式的載體,它能夠在對象生成或者初始化時直接將數據注入到對象中,也能夠經過將對象注入到對象數據域中的方式來注入對方法調用的依賴。這種依賴注入是能夠遞歸的,對象被逐層注入。
原創不易,轉載請註明出處。
若有錯誤的地方還請留言指正。
參考文獻:
《Spring技術內幕--深刻解析Spring框架與設計原理(第二版)》