2019独角兽企业重金招聘Python工程师标准>>>

loadBeanDefinitions 加载类的定义信息

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 {//将配置的Bean.xml 加载进来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();}}}

doLoadBeanDefinitions 从xml文件中加载 bean的定义信息

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {try {//加载信息,生成Document 对象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);}}

DefaultBeanDefinitionDocumentReader 通过此类,读取bean的定义信息

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getRegistry().getBeanDefinitionCount();//这里开始注册beandocumentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;
}protected void doRegisterBeanDefinitions(Element root) {// Any nested <beans> elements will cause recursion in this method. In// order to propagate and preserve <beans> default-* attributes correctly,// keep track of the current (parent) delegate, which may be null. Create// the new (child) delegate with a reference to the parent for fallback purposes,// then ultimately reset this.delegate back to its original (parent) reference.// this behavior emulates a stack of delegates without actually necessitating one.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);//这里开始解析documentparseBeanDefinitions(root, this.delegate);postProcessXml(root);this.delegate = parent;}//解析xml节点信息
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)) {//解析Spring 默认的xml标签<bean>parseDefaultElement(ele, delegate);}else {//解析注解,例如:<component-scanner>,<annotation-config>delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}

开始具体的解析,BeanDefinitionParserDelegate 定义了Spring 所有的默认的xml标签

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}//解析<bean>标签else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);}}// 解析完成之后,将bean 定义信息 保存到 BeanDefinitionHolder中
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);// Register an alias for the plain bean class name, if still possible,// if the generator returned the class name plus a suffix.// This is expected for Spring 1.2/2.0 backwards compatibility.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;}

// 将解析完成的BeanDefinitionHolder 放入到DefaultListableBeanFactory中去 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

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);}}BeanDefinition oldBeanDefinition;oldBeanDefinition = this.beanDefinitionMap.get(beanName);//如果已经存在了定义的bean信息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()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (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.isInfoEnabled()) {this.logger.info("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}else {if (this.logger.isDebugEnabled()) {this.logger.debug("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + oldBeanDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {//如果不存在if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {//将注册信息放入到map中this.beanDefinitionMap.put(beanName, beanDefinition);//定义新的已注册beanName列表List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);//将久的列表copy到新的listupdatedDefinitions.addAll(this.beanDefinitionNames);//将beanName放入到新的ListupdatedDefinitions.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 {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);this.manualSingletonNames.remove(beanName);}this.frozenBeanDefinitionNames = null;}if (oldBeanDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}}

转载于:https://my.oschina.net/u/582870/blog/872427

Spring 加载Bean流程相关推荐

  1. java spring 加载bean,Spring多种加载Bean方式解析

    1 定义bean的方式 常见的定义Bean的方式有: 通过xml的方式,例如: ? 通过注解的方式,在Class上使用@Component等注解,例如 ? 通过在@Configuration类下的@B ...

  2. 第三节 Spring加载bean的过程

    前言 通过前面两节的学习我们已经知道了Spring是如何解析XML与装载BeanDefinition的:在本章节中我们将继续学习bean的装载过程这将会面临更大的挑战,bean加载的功能实现远比bea ...

  3. Spring加载流程源码

    一.从AbstractApplicationContext的体系说起 第一,从类结构设计上看, 围绕着是否需要Refresh容器衍生出两个抽象类: GenericApplicationContext: ...

  4. Spring IOC 之 加载 Bean

    2019独角兽企业重金招聘Python工程师标准>>> 这段代码是 Spring 中编程式使用 IOC 容器,通过这四段简单的代码,我们可以初步判断 IOC 容器的使用过程 获取资源 ...

  5. Spring 加载、解析applicationContext.xml 流程

    概要 Spring 框架使用了BeanFactory 进行加载 xml 和生成 bean 实例.下面我们分析下Spring加载xml文件的过程. spring 版本是最新的 4.3.9 release ...

  6. 【死磕 Spring】----- IOC 之 加载 Bean

    原文:https://www.cmsblogs.com/category/1391374860344758272 『chenssy』 先看一段熟悉的代码: ClassPathResource reso ...

  7. Spring加载properties文件的两种方式

    2019独角兽企业重金招聘Python工程师标准>>> 在项目中如果有些参数经常需要修改,或者后期可能需要修改,那我们最好把这些参数放到properties文件中,源代码中读取pro ...

  8. spring加载顺序

    因为项目需求,要实现自定义注解然后通过spring扫描注解并放入缓存,我想到了BeanDefinitionRegistryPostProcessor接口,通过实现 BeanDefinitionRegi ...

  9. spring容器扩展功能之一:spring加载ApplicationContext.xml的四种方式

    容器加载Bean的常见两个类ApplicationContext和BeanFactory, 一.首先,看看spring中加载配置在xml中的Bean对象到容器 spring 中加载xml配置文件的方式 ...

最新文章

  1. 一文告诉你,如何使用Python构建一个“谷歌搜索”系统 | 内附代码
  2. ae中英文切换_AE技巧,AE CC软件如何切换中英文版
  3. iOS 设置app语言中文,比如 copy中文,拍照按钮cancel 中文
  4. APScheduler 浅析
  5. javadoc源码获取
  6. 退出Activity(转)
  7. Java 算法 找素数
  8. java swing jcheckbox_Swing JCheckBox类
  9. Vue:开发者友好性和易用性
  10. 5G 和 AI 双驱动,互联网有望迎来第二春
  11. 微服务的4大设计原则和19个解决方案
  12. Python如何运行单个.py文件而不是unittest
  13. 10 款富有创意的博客名片设计
  14. 查询mysql 的内存使用_如何查看MySQL内存使用情况
  15. Anchor-Free系列之CornerNet: Detecting Objects as Paired Keypoints
  16. 电子线路设计技巧5:CDRH系列贴片电感
  17. 红帽 -EX200-RHCSA 试题讲解-2
  18. SS2022 信号与系统期中练习题
  19. 2021年2月CFA一级机考报名截止时间!
  20. matlab中fsolve初值,求助一个新手简答问题 关于FSOLVE

热门文章

  1. Yii 一些小的问题
  2. MySQL基于mysqldump及lvmsnapshot备份恢复
  3. IIS出现问题时修改配置文件的几项说明
  4. AspxGridView 主子表设置
  5. 黑客攻破中国电信网络发布900个后台密码
  6. 【Linux】基于Openfile的multipath测试
  7. eclipse.ini配置eclipse的启动参数
  8. 微软程骉:智能医疗产业化应用的挑战和解决之道
  9. JWPlayer Uncaught Error: Invalid SRT file
  10. WebBrowser提交submit后界面不刷新的解决办法