SpringMVC經過一個配置文件描述Bean以及Bean之間的依賴關係,利用Java的反射機制實例化Bean並創建Bean之間的依賴關係。IOC容器在完成這些底層工做的基礎還提供了Bean的實例緩、生命週期、Bean實例代理等。BeanFacory是SpringMVC框架最核心的接口,他提供了最高級IOC的配置機制。ApplicationContext由BeanFactory派生而來,這也說明了 springMVC容器中運行的主體對象是 Bean,另外 ApplicationContext 繼承了 ResourceLoader 接口,使得 ApplicationContext 能夠訪問到任何外部資源,提供了更多面向實際應用的功能。SpringMVC初始化時在何時讀取配置咱們配置好的bean的文件,怎麼解析和註冊Bean?接下來咱們帶着問題來分析。 java
上一篇,咱們在介紹DispatcherServlet初始化的介紹時,父類FrameworkServlet在建立上下文時,調用了一個重啓上下文時,並初始化Bean。如圖所示:node

ConfigurableWebApplicationContext wac;調用了wac.refresh();方法,完成了對ApplicationContext的初始化,註冊啊,封裝bean的工做,由ConfigurableWebApplicationContext 的子類AbstractApplicationContext實現了bean初始化。咱們來了解一下上下文(容器)整個繼承關係。這邊的箭頭表示繼承或者實現的,如圖所示:web

從上圖咱們能夠看出,ApplicationContext也是繼承BeanFactory,ApplicationContext 也繼承了 ResourceLoader 接口,使得 ApplicationContext 能夠訪問到任何外部資源,提供了更多面向實際應用的功能,咱們經過refresh爲入口點,分析Bean整個初始化過程,並瞭解ApplicationContext的子類AbstractApplicationContext作了哪些工做並瞭解父類實現了哪些功能?每一個接口都有他使用的場合,它主要是爲了區分在 SpringMVC內部在操做過程當中對象的傳遞和轉化過程當中,對對象的數據訪問所作的限制。咱們如今先頭腦中有這個繼承的關係圖,之後深度的瞭解,比較不會那麼暈,這樣思路就比較清晰,咱們以refresh爲入口點,帶着這些問題進行解析。算法
refresh方法的源代碼以下:spring
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
-
- prepareRefresh();
-
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
-
- prepareBeanFactory(beanFactory);
- try {
-
- postProcessBeanFactory(beanFactory);
-
- invokeBeanFactoryPostProcessors(beanFactory);
-
- registerBeanPostProcessors(beanFactory);
-
- initMessageSource();
-
- initApplicationEventMulticaster();
-
- onRefresh();
-
- registerListeners();
-
- finishBeanFactoryInitialization(beanFactory);
-
- finishRefresh();
- }catch (BeansException ex) {
-
- destroyBeans();
-
- cancelRefresh(ex);
-
- throw ex;
- }
- }
- }
這個方法作了不少事情,主要有初始化beanFactory 、註冊BeanFactory處理器等工做。咱們接下來對裏面重要的功能進行解析,它怎麼讀取咱們配置文件並解析文件和註冊配置文件裏的bean。數組
初始化beanFactory工廠時,就對讀取咱們配置文件並解析文件和註冊配置文件裏的Bean,是由AbstractApplicationContext.obtainFreshBeanFactory方法實現的,源代碼以下:數據結構
- **
- * Tell the subclass to refresh the internal bean factory.
- * @return the fresh BeanFactory instance
- * @see #refreshBeanFactory()
- * @see #getBeanFactory()
- */
- protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
- refreshBeanFactory();
- ConfigurableListableBeanFactory beanFactory = getBeanFactory();
- if (logger.isDebugEnabled()) {
- logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
- }
- return beanFactory;
- }
- @Override
- protected final void refreshBeanFactory() throws BeansException {
- if (hasBeanFactory()) {
- destroyBeans();
- closeBeanFactory();
- }
- try {
- DefaultListableBeanFactory beanFactory = createBeanFactory();
- beanFactory.setSerializationId(getId());
- customizeBeanFactory(beanFactory);
- loadBeanDefinitions(beanFactory);
- synchronized (this.beanFactoryMonitor) {
- this.beanFactory = beanFactory;
- }
- }
- catch (IOException ex) {
- throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
- }
- }
第一步:併發
refreshBeanFactory 先銷燬全部Bean,關閉BeanFactory,而後從新建立一個BeanFactory,並將其賦給BeanFactory實例變量。咱們先看一下它怎麼建立BeanFactory? 框架
createBeanFactory這個方法是建立新的BeanBeanFactory ,而BeanFactory 的原始對象是 DefaultListableBeanFactory,這個很是關鍵,由於他設計到後面對這個對象的多種操做,DefaultListableBeanFactory是整個Bean加載的核心部分,是SpringMVC註冊及加載Bean的默認實現。ide
- protected DefaultListableBeanFactory createBeanFactory() {
- return new DefaultListableBeanFactory(getInternalParentBeanFactory());
- }
初始化BeanFactory時,判斷是否有父BeanFactory,若是有設置,若是沒有就爲null。
- protected BeanFactory getInternalParentBeanFactory() {
- return (getParent() instanceof ConfigurableApplicationContext) ?
- ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent();
- }
獲取父BeanFactory
- public DefaultListableBeanFactory(BeanFactory parentBeanFactory) {
- super(parentBeanFactory);
- }
- public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
- this();
- setParentBeanFactory(parentBeanFactory);
- }
setParentBeanFactory設置父BeanFactory。
咱們對BeanFactory繼承關係瞭解一下,爲後面的解析提供比較清晰的路線,如圖所示:

如今BeanFactory建立好了,ApplicationContext 繼承了BeanFactory,還繼承了 ResourceLoader 接口,使得 ApplicationContext 能夠訪問到任何外部資源,提供了更多面向實際應用的功能,接下來咱們進行第二步,分析解析配置文件和註冊Bean。
第二步:先轉碼在讀取配置文件
loadBeanDefinitions(beanFactory) 將找到答案,這個方法將開始加載、解析 Bean 的定義,也就是把用戶定義的數據結構轉化爲 Ioc 容器中的特定數據結構。咱們要分析一下這個方法。
- @Override
- protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
-
- XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
-
-
-
- beanDefinitionReader.setEnvironment(this.getEnvironment());
- beanDefinitionReader.setResourceLoader(this);
- beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
-
-
-
- initBeanDefinitionReader(beanDefinitionReader);
- loadBeanDefinitions(beanDefinitionReader);
- }

XmlBeanDefinitionReader 來讀取並解析 xml 文件,XmlBeanDefinitionReader 是 BeanDefinitionReader 接口的實現。咱們來看一下繼承關係,如圖所示:

BeanDefinitionReader 讀取Resource所指向的配置文件資源,而後解析配置文件,配置文件中每個Bean解析成一個BeanDefinition對象,並保存到BeanDefinitionRegistry中。咱們這邊先了解一下。先實現經過BeanFactory建立XmlBeanDefinitionReader對象,而後爲XmlBeanDefinitionReader 配置ResourceLoader,由於DefaultResourceLoader是父類,因此this能夠直接被使用,ResourceLoader對資源的加載。 如圖所示:


咱們如今獲取外面的資源也設置好了,咱們進行深刻解析,loadBeanDefinitions方法源代碼以下:
- protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
- String[] configLocations = getConfigLocations();
- if (configLocations != null) {
- for (String configLocation : configLocations) {
- reader.loadBeanDefinitions(configLocation);
- }
- }
- }
- @Override
- public String[] getConfigLocations() {
- return super.getConfigLocations();
- }
- protected String[] getConfigLocations() {
- return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
- }
由 AbstractRefreshableWebApplicationContext父類AbstractRefreshableConfigApplicationContext實現getConfigLocations方法,獲取了web.xml配置的param-value的值,而後getConfigLocations保存在數組裏面。如圖所示:

如今獲取了param-value的值,接下去就開始讀取配置文件,具體實現時由XmlBeanDefinitionReader父類AbstractBeanDefinitionReader實現的,
reader.loadBeanDefinitions(configLocation);源代碼:
- public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
- return loadBeanDefinitions(location, null);
- }
- public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
- ResourceLoader resourceLoader = getResourceLoader();
- if (resourceLoader == null) {
- throw new BeanDefinitionStoreException(
- "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
- }
-
- if (resourceLoader instanceof ResourcePatternResolver) {
-
- try {
- Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
- int loadCount = loadBeanDefinitions(resources);
- if (actualResources != null) {
- for (Resource resource : resources) {
- actualResources.add(resource);
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
- }
- return loadCount;
- }
- catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "Could not resolve bean definition resource pattern [" + location + "]", ex);
- }
- }
- else {
-
- Resource resource = resourceLoader.getResource(location);
- int loadCount = loadBeanDefinitions(resource);
- if (actualResources != null) {
- actualResources.add(resource);
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
- }
- return loadCount;
- }
- }
這個方法有一個ResourcePatternResolver加載了web.xml配置的param-value對應的資源,例如classpath:xxx*.xml 加載了xxx下爲xml爲後綴的文件資源,loadBeanDefinitions進行對加載進來的資源進行解析。在解析以前先進行轉碼,是經過EncodedResource對資源文件進行轉碼,源代碼以下:
- public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
- return loadBeanDefinitions(new EncodedResource(resource));
- }
對資源文件轉碼完,就開始讀進來,以流的形式,源代碼以下:
- public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
- Assert.notNull(encodedResource, "EncodedResource must not be null");
- if (logger.isInfoEnabled()) {
- logger.info("Loading XML bean definitions from " + encodedResource.getResource());
- }
-
- Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
- if (currentResources == null) {
- currentResources = new HashSet<EncodedResource>(4);
- this.resourcesCurrentlyBeingLoaded.set(currentResources);
- }
- if (!currentResources.add(encodedResource)) {
- throw new BeanDefinitionStoreException(
- "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
- }
- try {
- InputStream inputStream = encodedResource.getResource().getInputStream();
- try {
- InputSource inputSource = new InputSource(inputStream);
- if (encodedResource.getEncoding() != null) {
- inputSource.setEncoding(encodedResource.getEncoding());
- }
- return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
- }
- finally {
- inputStream.close();
- }
- }
- catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "IOException parsing XML document from " + encodedResource.getResource(), ex);
- }
- finally {
- currentResources.remove(encodedResource);
- if (currentResources.isEmpty()) {
- this.resourcesCurrentlyBeingLoaded.remove();
- }
- }
- }
說明:
(1)getValidationModeForResource(resource);獲取對XML文件的驗證模式
(2)Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());加載XML文件,並獲取對應的Document。這邊是把配置文件讀進來,以Document 形式存儲。
(3)registerBeanDefinitions(doc, resource);解析並註冊bean。
第三步:解析並註冊bean,解析 Bean 的定義,也就是把用戶定義的數據結構轉化爲 Ioc 容器中的特定數據結構。
咱們繼續第二步中先把文件讀進來,接下來進行解析和註冊是由registerBeanDefinitions(doc, resource);這個方法實現的,源代碼以下:
- public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
- BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
- documentReader.setEnvironment(this.getEnvironment());
- int countBefore = getRegistry().getBeanDefinitionCount();
- documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
- return getRegistry().getBeanDefinitionCount() - countBefore;
- }
- <span style="color:#ff0000;">
- public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
- this.readerContext = readerContext;
- logger.debug("Loading bean definitions");
- Element root = doc.getDocumentElement();
- doRegisterBeanDefinitions(root);
- }
-
- protected void doRegisterBeanDefinitions(Element root) {
- String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
- if (StringUtils.hasText(profileSpec)) {
- Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
- String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
- profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
- if (!this.environment.acceptsProfiles(specifiedProfiles)) {
- return;
- }
- }
- BeanDefinitionParserDelegate parent = this.delegate;
- this.delegate = createDelegate(this.readerContext, root, parent);
- preProcessXml(root);
- parseBeanDefinitions(root, this.delegate);
- postProcessXml(root);
- this.delegate = parent;
- }
說明:
(1)public static final String PROFILE_ATTRIBUTE = "profile";判斷bean節點是否認義了profile屬性,若是有,就要到環境變量中去尋找
(2)BeanDefinitionParserDelegate是對BeanDefinition的解析的,這裏就不具體分析了。
(2) parseBeanDefinitions(root, this.delegate);把bean註冊到BeanDefinition對象中。
這個 parseBeanDefinitions(root, this.delegate)開始註冊了,咱們解析到重點了,源代碼以下:
- protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
- if (delegate.isDefaultNamespace(root)) {
- NodeList nl = root.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element ele = (Element) node;
- if (delegate.isDefaultNamespace(ele)) {
- parseDefaultElement(ele, delegate);
- }
- else {
- delegate.parseCustomElement(ele);
- }
- }
- }
- }
- else {
- delegate.parseCustomElement(root);
- }
- }
- private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
-
- if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
- importBeanDefinitionResource(ele);
- }
-
- else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
- processAliasRegistration(ele);
- }
-
- else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
- processBeanDefinition(ele, delegate);
- }
- else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
-
- doRegisterBeanDefinitions(ele);
- }
- }
- protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
- BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
- if (bdHolder != null) {
- bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
- try {
-
- BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
- }
- catch (BeanDefinitionStoreException ex) {
- getReaderContext().error("Failed to register bean definition with name '" +
- bdHolder.getBeanName() + "'", ele, ex);
- }
-
- getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
- }
- }
解析Bean的id、name等元素設置到BeanDefinition而後放到放到BeanDefinitionHolder中,這個是由parseBeanDefinitionElement進行處理的,源代碼以下:
- public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
-
- String id = ele.getAttribute(ID_ATTRIBUTE);
-
- String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
-
- List<String> aliases = new ArrayList<String>();
- if (StringUtils.hasLength(nameAttr)) {
- String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
- aliases.addAll(Arrays.asList(nameArr));
- }
-
- String beanName = id;
- if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
- beanName = aliases.remove(0);
- if (logger.isDebugEnabled()) {
- logger.debug("No XML 'id' specified - using '" + beanName +
- "' as bean name and " + aliases + " as aliases");
- }
- }
-
- if (containingBean == null) {
- checkNameUniqueness(beanName, aliases, ele);
- }
- AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
- if (beanDefinition != null) {
- if (!StringUtils.hasText(beanName)) {
- try {
- if (containingBean != null) {
- beanName = BeanDefinitionReaderUtils.generateBeanName(
- beanDefinition, this.readerContext.getRegistry(), true);
- }
- else {
- beanName = this.readerContext.generateBeanName(beanDefinition);
-
-
-
- String beanClassName = beanDefinition.getBeanClassName();
- if (beanClassName != null &&
- beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
- !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
- aliases.add(beanClassName);
- }
- }
- if (logger.isDebugEnabled()) {
- logger.debug("Neither XML 'id' nor 'name' specified - " +
- "using generated bean name [" + beanName + "]");
- }
- }
- catch (Exception ex) {
- error(ex.getMessage(), ele);
- return null;
- }
- }
- String[] aliasesArray = StringUtils.toStringArray(aliases);
- return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
- }
-
- return null;
- }
- public AbstractBeanDefinition parseBeanDefinitionElement(
- Element ele, String beanName, BeanDefinition containingBean) {
-
- this.parseState.push(new BeanEntry(beanName));
-
- String className = null;
- if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
- className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
- }
-
- try {
-
- String parent = null;
- if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
- parent = ele.getAttribute(PARENT_ATTRIBUTE);
- }
- AbstractBeanDefinition bd = createBeanDefinition(className, parent);
-
- parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
- bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
-
- parseMetaElements(ele, bd);
- parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
- parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
-
- parseConstructorArgElements(ele, bd);
-
- parsePropertyElements(ele, bd);
- parseQualifierElements(ele, bd);
-
- bd.setResource(this.readerContext.getResource());
- bd.setSource(extractSource(ele));
-
- return bd;
- }
- catch (ClassNotFoundException ex) {
- error("Bean class [" + className + "] not found", ele, ex);
- }
- catch (NoClassDefFoundError err) {
- error("Class that bean class [" + className + "] depends on not found", ele, err);
- }
- catch (Throwable ex) {
- error("Unexpected failure during bean definition parsing", ele, ex);
- }
- finally {
- this.parseState.pop();
- }
-
- return null;
- }
對bean的id、name、class等屬性的解析並設置到BeanDefinition而後放到放到BeanDefinitionHolder中,並放入到IOC容器中創建對應的數據結構。
如今IOC容器中已經創建對應的數據結構,接下來開始對對bean進行註冊,
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());源代碼以下:
- public static void registerBeanDefinition(
- BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
- throws BeanDefinitionStoreException {
-
-
- String beanName = definitionHolder.getBeanName();
- registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
-
-
- String[] aliases = definitionHolder.getAliases();
- if (aliases != null) {
- for (String aliase : aliases) {
- registry.registerAlias(beanName, aliase);
- }
- }
- }
- public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
- throws BeanDefinitionStoreException {
- Assert.hasText(beanName, "Bean name must not be empty");
- Assert.notNull(beanDefinition, "BeanDefinition must not be null");
-
- if (beanDefinition instanceof AbstractBeanDefinition) {
- try {
- ((AbstractBeanDefinition) beanDefinition).validate();
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
- "Validation of bean definition failed", ex);
- }
- }
- synchronized (this.beanDefinitionMap) {
- Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
- if (oldBeanDefinition != null) {
- if (!this.allowBeanDefinitionOverriding) {
- throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
- "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
- "': There is already [" + oldBeanDefinition + "] bound.");
- }
- else {
- if (this.logger.isInfoEnabled()) {
- this.logger.info("Overriding bean definition for bean '" + beanName +
- "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
- }
- }
- }
- else {
- this.beanDefinitionNames.add(beanName);
- this.frozenBeanDefinitionNames = null;
- }
- this.beanDefinitionMap.put(beanName, beanDefinition);
- }
-
- resetBeanDefinition(beanName);
- }
先檢查是否是有相同名字的BeanDefinition已經在IoC容器中註冊了,若是有相同名字的BeanDefinition,但又不容許覆蓋,那麼會拋出異常,若是能夠能夠覆蓋,或者IOC容器中沒註冊,而後把Bean的名字存入到beanDefinitionNames的同時,把beanName做爲Map的key,把beanDefinition做爲value存入到IoC容器持有的BeanDefinitionMap中去。
總結:
(1)SpringMVC先建立BeanFactory時先銷燬全部Bean,關閉BeanFactory,而後從新建立一個BeanFactory,並將其賦給BeanFactory實例變量。
(2)建立好了BeanFactory,並設置好環境,ApplicationContext 繼承了 ResourceLoader 接口,並經過ResourcePatternResolver加載了web.xml配置的param-value對應的資源,例如classpath:xxx*.xml 加載了xxx下爲xml爲後綴的文件資源,loadBeanDefinitions進行對加載進來的資源進行解析,在解析以前先進行轉碼,是經過EncodedResource對資源文件進行轉碼
(3)對讀取進來的配置文件進行驗證,是不是XML格式的,而後配置文件中的Bean的id、name、class等屬性的解析並設置到BeanDefinition而後放到放到BeanDefinitionHolder中,並放入到IOC容器中創建對應的數據結構。是以Document形式的存儲的。
(4)在IOC容器中已經創建對應的數據結構,解析 Bean 的定義和註冊,先檢查是否是有相同名字的BeanDefinition已經在IoC容器中註冊了,若是有相同名字的BeanDefinition,但又不容許覆蓋,那麼會拋出異常,若是能夠能夠覆蓋,或者IOC容器中沒註冊,而後把Bean的名字存入到beanDefinitionNames的同時,把beanName做爲Map的key,把beanDefinition做爲value存入到IoC容器持有的BeanDefinitionMap中去。
咱們如今註冊好,要實例化,還有Spring最核心的IOC依賴注入,怎麼實例化並依賴注入,帶着這些問題?下一篇咱們繼續解析。