demo 读取配置文件启动Spring:
1 2 3 4 5 6 7 public class IOCDemo { public static void main (String args[]) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-ioc.xml" ); IOCService iocService=context.getBean(IOCService.class ) ; System.out.println(iocService.hollo()); } }
ClassPathXmlApplicationContext 继承关系 继承关系图:
最上方的 ApplicationContext 则是大名鼎鼎的Spring核心上下文了。
左下角的就是ClassPathXmlApplicationContext、与它同级的是FileSystemXmlApplicationContext。都是通过加载配置文件来启动Spring的,只不过一个是从程序内加载一个是从系统内加载。
AnnotationConfigApplicationContext比较值得我们关注,这个类是用来处理注解式编程的。详细请移步
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { private Resource[] configResources; public ClassPathXmlApplicationContext (ApplicationContext parent) { super (parent); } public ClassPathXmlApplicationContext (String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super (parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } }
类构造主要有 setConfigLocations
和 refresh
这两个方法,这两个方法也是IOC的核心。
setConfigLocations
方法主要工作:
创建环境对象ConfigurableEnvironment
处理ClassPathXmlApplicationContext传入的字符串中的占位符
refresh
方法主要工作:
检查环境
创建BeanFactory
解析xml配置文件
创建Bean
注册Bean
扩展点
初始化
setConfigLocations() 源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public void setConfigLocations (String... locations) { if (locations != null ) { Assert.noNullElements(locations, "Config locations must not be null" ); this .configLocations = new String[locations.length]; for (int i = 0 ; i < locations.length; i++) { this .configLocations[i] = resolvePath(locations[i]).trim(); } } else { this .configLocations = null ; } } protected String resolvePath (String path) { return getEnironment().resolveRequiredPlaceholders(path); }
这里会读取传入的 locations 数组并遍历,具体操作是由resolvePath
方法实现。
创建环境变量 看一下 getEniroment
方法:
1 2 3 4 5 6 public ConfigurableEnvironment getEnvironment () { if (this .environment == null ) { this .environment = createEnvironment(); } return this .environment; }
ConfigurableEnvironment 继承关系图:
它直接继承类 Environment
和 ConfigurablePropertyResolver
。
这个接口比较重要的两部分作用:
spring.profile配置
系统资源Property
接着看 createEnvironment()
方法:
1 2 3 protected ConfigurableEnvironment createEnvironment () { return new StandardEnvironment(); }
返回 StandardEnvironment
类,而这个类中的customizePropertySources
方法就会往资源列表中添加Java进程中的变量和系统的环境变量:
1 2 3 4 protected void customizePropertySources (MutablePropertySources propertySources) { propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); }
处理占位符 回到 resovePath.resolveRequiredPlaceholders
方法:
这个方法主要就是处理所有使用${}方式的占位符,这里主要是为了处理 ClassPathXmlApplicationContext
传过来的占位符。
1 ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:${prefixName}-spring.xml" );
refresh 读取环境及系统变量、配置文件名称解析完毕后,就到了最关键的一步refresh
方法。
它也是spring管理bean的核心,bean的创建、注册、初始化都由这个方法完成 。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 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) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
检查环境 prepareRefresh
方法主要做一些准备工作,记录容器的启动时间、标记“已启动”状态、检查环境变量等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 protected void prepareRefresh () { this .startupDate = System.currentTimeMillis(); this .closed.set(false ); this .active.set(true ); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this ); } initPropertySources(); getEnvironment().validateRequiredProperties(); this .earlyApplicationEvents = new LinkedHashSet<>(); }
这个方法最重要的是倒数二三行,具体详情请访问:准备环境
obtainFreshBeanFactory()* 这个方法很长,这里先总结它的主要工作:
初始化一个ConfigurableListableBeanFactory容器
Rousource接口处理xml配置文件的流,解析配置文件
根据解析出的配置dom,创建BeanDefinition示例
注册了所有的BeanDefinition到beanDefinitionMap
源码:
1 2 3 4 5 6 7 8 9 10 11 protected ConfigurableListableBeanFactory obtainFreshBeanFactory () { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
解析这个方法之前,我们先要了解两个核心类 DefaultListableBeanFactory
和 BeanDefinition
。
DefaultListableBeanFactory 继承关系:
BeanFacoty 有三个直接子类 ListableBeanFactory
、HierarchicalBeanFactory
和 AutowireCapableBeanFactory
;
DefaultListableBeanFactory
为最终默认实现,它实现了所有接口。
实际上我们应用spring也是通过ApplicationContex和DefaultListableBeanFactory一起来完成的 。
BeanDefinition 我们知道 BeanFactory 是一个 Bean 容器,而 BeanDefinition 就是 Bean 的一种形式(它里面包含了 Bean 指向的类、是否单例、是否懒加载、Bean 的依赖关系等相关的属性)。BeanFactory 中就是保存的 BeanDefinition。
看看BeanDefinition的接口源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 public interface BeanDefinition extends AttributeAccessor , BeanMetadataElement { String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON; String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE; void setParentName (String parentName) ; String getParentName () ; void setBeanClassName (String beanClassName) ; String getBeanClassName () ; void setScope (String scope) ; String getScope () ; void setLazyInit (boolean lazyInit) ; boolean isLazyInit () ; void setDependsOn (String... dependsOn) ; String[] getDependsOn(); void setAutowireCandidate (boolean autowireCandidate) ; boolean isAutowireCandidate () ; void setPrimary (boolean primary) ; boolean isPrimary () ; void setFactoryBeanName (String factoryBeanName) ; String getFactoryBeanName () ; void setFactoryMethodName (String factoryMethodName) ; String getFactoryMethodName () ; ConstructorArgumentValues getConstructorArgumentValues () ; MutablePropertyValues getPropertyValues () ; boolean isSingleton () ; boolean isPrototype () ; boolean isAbstract () ; int getRole () ; String getDescription () ; String getResourceDescription () ; BeanDefinition getOriginatingBeanDefinition () ; }
refreshBeanFactory() 我们回到 obtainFreshBeanFactory
,看一下 refreshBeanFactory
方法。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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); } }
进入 loadBeanDefinitions
方法。
loadBeanDefinitions() 读取配置文件 1 2 3 4 5 6 7 8 9 10 11 12 @Overrideprotected 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); }
1 2 3 4 5 6 7 8 9 10 protected void loadBeanDefinitions (XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null ) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null ) { reader.loadBeanDefinitions(configLocations); } }
第一个if是看有没有系统指定的配置文件,如果没有的话就走第二个if加载我们最开始传入的 classpath:application-ioc.xml
XmlBeanDefinitionReader 是我们解析xml配置的核心类。
XmlBeanDefinitionReader ,它的父类是 AbstractBeanDefinitionReader
它实现了 BeanDefinitionReader
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected AbstractBeanDefinitionReader (BeanDefinitionRegistry registry) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null" ); this .registry = registry; if (this .registry instanceof ResourceLoader) { this .resourceLoader = (ResourceLoader)this .registry; } else { this .resourceLoader = new PathMatchingResourcePatternResolver(); } if (this .registry instanceof EnvironmentCapable) { this .environment = ((EnvironmentCapable)this .registry).getEnvironment(); } else { this .environment = new StandardEnvironment(); } }
它提供了读取环境变量,加载location资源,以及 BeanDefinitionRegistry的 注册Bean方法。
Resourse 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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<>(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(); } } }
中间省略了一些源码,其实这几个方法的目的就是把流交给 Resource
接口来处理,它的每一个实现类都代表了一种资源的访问策略,这里用的就是EncodedResource。
DOM解析 进去看 doLoadBeanDefinitions()
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 protected int doLoadBeanDefinitions (InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid" , ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid" , ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }
xml转dom解析这里不用费神了,主要是 registerBeanDefinitions()
。
注册 Bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public int registerBeanDefinitions (Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource)); return getRegistry().getBeanDefinitionCount() - countBefore; } @Override 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) { BeanDefinitionParserDelegate parent = this .delegate; this .delegate = createDelegate(getReaderContext(), root, parent); if (this .delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isInfoEnabled()) { logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return ; } } } preProcessXml(root); parseBeanDefinitions(root, this .delegate); postProcessXml(root); this .delegate = parent; }
接下来就是具体解析xml配置文件的方法 parseBeanDefinitions()
;
解析xml标签 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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); } }
看一下 default 标签的处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 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); } }
看一下bean标签的处理方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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)); } }
看一下第一行的 parseBeanDefinitionElement
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public BeanDefinitionHolder parseBeanDefinitionElement (Element ele) { return parseBeanDefinitionElement(ele, null ); } 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 ; }
看一下这个方法的 parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)
。
这个方法就是根据配置创建 BeanDefinition 实例的方法,前面山路十八弯,其中解析xml占据了大部分源码。。。
创建 BeanDefinition* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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 ; }
通过 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement
进行元素解析,返回BeanDefinitionHolder,返回的实例包含了配置文件中配置的各种属性了,比如class、name、id、alias之类的属性。
注册Bean 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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)); } }
注册操作委托给了BeanDefinitionReaderUtils,看看真正注册Bean的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 alias : aliases) { registry.registerAlias(beanName, alias); } } }
这里我们要注意这个类 BeanDefinitionRegistry
接口, 我们注册Bean、删除Bean,用到的都是这个类。当然我们用的是它的实现类DefaultListableBeanFactory
的方法。
还要往里看。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 @Override 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 oldBeanDefinition; oldBeanDefinition = this .beanDefinitionMap.get(beanName); if (oldBeanDefinition != null ) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound." ); } else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { if (this .logger.isWarnEnabled()) { this .logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]" ); } } else if (!beanDefinition.equals(oldBeanDefinition)) { if (this .logger.isWarnEnabled()) { this .logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]" ); } } else { if (this .logger.isInfoEnabled()) { this .logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]" ); } } this .beanDefinitionMap.put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { synchronized (this .beanDefinitionMap) { this .beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<String>(this .beanDefinitionNames.size() + 1 ); updatedDefinitions.addAll(this .beanDefinitionNames); updatedDefinitions.add(beanName); this .beanDefinitionNames = updatedDefinitions; if (this .manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<String>(this .manualSingletonNames); updatedSingletons.remove(beanName); this .manualSingletonNames = updatedSingletons; } } } else { this .beanDefinitionMap.put(beanName, beanDefinition); this .beanDefinitionNames.add(beanName); this .manualSingletonNames.remove(beanName); } this .frozenBeanDefinitionNames = null ; } if (oldBeanDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }
到这里已经初始化了 Bean 容器,的配置也相应的转换为了一个个BeanDefinition,然后注册了所有的 BeanDefinition 到beanDefinitionMap,
总结 其实这一长串源码下来,关于读取配置文件、创建Bean、加载Bean,实际上是: BeanDefinitionReader 如何将 Resource 转换为 IoC 容器独特的数据存储对象:BeanDefinition
当然这里 bean 还没有初始化,只是完成了bean的注册。关于Bean初始化的内容请看下文 Spring——IOC源码解析下