`

BeanDefinition的载入与注册

 
阅读更多

以下说法若有不对的地方欢迎大家指正

我这里用的是断点不断跟进的方式 

spring的版本为3.2.2

 

以下是一张方法的调用图 方便理解

 

最近在看spring的IoC具体实现

其实也没有什么太大的心得 就是不断进行断点调试 然后看一下过程

这个过程其实并不复杂 只是一层层不断调用有点头晕罢了

 

以下我来说说具体的BeanDefinition载入和注册的过程

首先我这边是以ClassPathXmlApplicationContext为IoC容器的 他底下是维护了一个DefaultListableBeanFactory

bean的注册工作其实是在DefaultListableBeanFactory中完成的

这个Map的定义和实现如下:

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

 

这边是主要的过程(如果我写错了 谢谢指正^_^)

1、 通过XML解析接到Document对象标准的(org.w3c.dom.Document)

2、 在documentReader中实现这个按照Spring的Bean规则进行解析的过程

3、 实际的解析工作是交给documentReader中的BeanDefinitionParserDelegate完成的

4、 BeanDefinitionParserDelegate把解析的beanDefinition交给BeanDefinitionHolder

5、 在documentReader中调用BeanDefinitionReaderUtils.registerBeanDefinition(,)向IoC容器中注册

 

为了直观 我把一些主要的代码放出来并写上自己的注释 以下:

 

// XmlBeanDefinitionsReader中的方法
         protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			int validationMode = getValidationModeForResource(resource);
			// 标准的org.w3c.dom.Document对象
			Document doc = this.documentLoader.loadDocument(
					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
			// 完成标准的document到spring定义的bean规则解析的过程
			return registerBeanDefinitions(doc, resource);
		}
		catch (BeanDefinitionStoreException ex) {
		... ...

 

    // 同样是XmlBeanDefinitionsReader中的方法
	public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		// 得到一个BeanDefinitionDocumentReader的对象来按照bean规则解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		documentReader.setEnvironment(this.getEnvironment());
		// 获取解析前的bean数目 第一次的话应该是0
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 具体的解析过程以下完成
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

 

	// 以上的documentReader.registerBeanDefinitions(,)方法调用了DefaultBeanDefinitionDocumentReader中的方法
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		// 得到根元素
		Element root = doc.getDocumentElement();
		// 这边开始做解析
		doRegisterBeanDefinitions(root);
	}

 

 

	// 同样是调用了DefaultBeanDefinitionDocumentReader中的方法
	protected void doRegisterBeanDefinitions(Element root) {
	    // 这部分是关于profile的(spring 3.1之后才有的吧?) 绕过
		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的对象
		// 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 = createHelper(this.readerContext, root, parent);

		// 在DefaultBeanDefinitionDocumentReader中什么都不做
		preProcessXml(root);
		// 这边就是具体的解析了
		parseBeanDefinitions(root, this.delegate);
		// 在DefaultBeanDefinitionDocumentReader中什么都不做
		postProcessXml(root);
                // 还原
		this.delegate = parent;
	}

 

 

	// DefaultBeanDefinitionDocumentReader中的方法
	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);
		}
	}

 

 

	// 以上方法的parseDefaultElement如下 同样是DefaultBeanDefinitionDocumentReader中的方法
	// 根据不同的名称执行不同的操作
	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)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

 

 

	//同样是DefaultBeanDefinitionDocumentReader中的方法 这是以上的processBeanDefinition(ele, delegate)
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
		    // bdHolder就是BeanDefinitionHolder 
			// 解析实际都是靠BeanDefinitionParserDelegate中的方法完成的 这里面的代码太多了就不跟进了
			// 需要的可以自己去看下
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				// 这句话就是向BeanFactory注册bean 
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

 

 

	// BeanDefinitionReaderUtils中的静态方法
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		// 传入的这个registry其实就是在之前的DefaultListableBeanFactory实例 因为
		// DefaultListableBeanFactory实现了BeanDefinitionRegistry接口可以注册bean
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
	}

 

 

	// DefaultListableBeanFactory中的方法
	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);
			// 如果存在了同名的bean
			if (oldBeanDefinition != null) {
			    //如果不允许bean的覆盖的话就会抛出异常
				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;
			}
			// 可以看到其实内部还是一个Map的结构来维护的
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}

		resetBeanDefinition(beanName);
	}

 

具体过程如上

这边只是阐述了一下这个过程 有兴趣的可以自己跟进查看更详细的解析过程

  • 大小: 295.2 KB
0
0
分享到:
评论

相关推荐

    BeanDefinition存储体系.vsdx

    Spring BeanDefinition 类图结构,形象展示Spring是如何存储Bean信息的。通过类图和源码更好的理解Spring BeanDefinition存储结构

    Spring Boot: Bean definition overriding

    在本文中,我将讨论棘手的Spring Boot bean定义覆盖机制。 为了使您对该主题更加清楚,让我们从小测验开始。请看下一个简单的例子。 因此,我们有2种配置,它们使用名称beanName实例化bean,在主应用程序中,我们仅...

    BeanDefinition基础信息讲解

    BeanDefinition基础信息讲解 BeanDefinition是Spring框架中一个非常重要的概念,它是Bean的元数据,用于描述Bean的各种信息,例如Bean的名称、类名称、Scope、依赖关系等。在Spring框架中,BeanDefinition是一个...

    Spring源码学习二:BeanDefinition解析1

    除此之外,BeanDefinition还包含属性值(属性与值的键值对)、构造函数参数、属性注入点(property references)和方法注入点(method injection points)等信息。这些信息通过实现BeanDefinition的子接口(如...

    Spring中眼花缭乱的BeanDefinition.docx

    Spring中的BeanDefinition是核心概念,它是Spring IOC容器的基础,用于描述Bean的元数据,包括Bean的行为、依赖关系和其他配置信息。BeanDefinition包含了Bean的全限定类名、作用域、生命周期回调方法、依赖的其他...

    Spring源码学习五:BeanDefinition装载1

    Spring 源码学习五:BeanDefinition 装载 1 在 Spring 框架中,BeanDefinition 是一个核心概念,它描述了一个 Bean 的定义,包括其依赖项、作用域、生命周期等信息。在本篇文章中,我们将深入探讨 Spring 的源码,...

    Spring源码学习四:BeanDefinition装载前奏曲1

    在深入Spring源码的学习过程中,我们主要关注BeanDefinition的装载过程。BeanDefinition是Spring框架的核心概念,它包含了关于Bean的所有元数据,如类名、属性、依赖关系等。在Spring初始化时,会读取XML配置文件,...

    撸一撸Spring Framework-IoC-BeanDefinition(csdn)————程序.pdf

    BeanDefinition就是实现这一概念的关键元素,它包含了关于一个bean的所有元信息,用于描述bean的属性、行为以及与其他bean的关系。 在BeanFactory篇中,我们了解到BeanFactory在启动时会从配置元信息(通常是XML...

    Spring Bean Factory, Bean definition 结构图;processOn

    Spring Bean Factory, Bean definition 结构图;processOn

    00000025_beandefine的用法.rar

    二、BeanDefinition的注册与加载 在Spring容器启动时,会通过BeanDefinitionReader读取XML配置文件或通过AnnotationConfigApplicationContext读取注解配置,将BeanDefinition注册到BeanDefinitionRegistry中。注册...

    spring运行过程中动态注册bean

    #### 创建BeanDefinition 接下来,使用`BeanDefinitionBuilder`来构建Bean的定义。`BeanDefinitionBuilder`提供了简洁的API来定义一个Bean的所有属性和行为,包括它的类型、依赖注入的属性等。在这个例子中,我们...

    Spring之动态注册bean的实现方法

    在 Spring 中,我们可以使用 BeanDefinition 来实现动态注册 Bean。BeanDefinition 是 Spring 框架中的一种核心概念,它提供了一种灵活的方式来定义 Bean。 首先,我们需要创建一个 BeanDefinitionBuilder 对象,...

    spring源码学习

    ##### 1.1 BeanDefinition定义与继承体系 **BeanDefinition** 是Spring框架中一个非常重要的概念,它本质上是用来描述一个Bean(即Java对象)的配置元数据。这些元数据包含了Bean的属性值、依赖关系、生命周期回调...

    Spring核心API介绍-后续还会更新.pdf

    在BeanDefinition中,有两个与Bean生命周期相关的属性:initMethodName和destroyMethodName。它们分别指定了Bean初始化和销毁时要调用的方法,这对于实现Bean的生命周期回调非常关键。例如,当Bean被创建后,Spring...

    spring 动态注册 bean

    spring 动态注册 beanspring 动态注册 beanspring 动态注册 bean

    EJB实验报告。实验一:使用Session Bean和JDBC技术完成登录和注册功能

    【实验一:使用Session Bean和JDBC技术完成登录和注册功能】 实验一旨在让学生掌握Session Bean的基本功能,包括无状态(Stateless)和有状态(Stateful)Session Bean的使用,以及如何配置服务器和客户端。此外,...

    Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等).doc

    首先,我们需要从 beanDefinitionMap 中通过 beanName 获得 BeanDefinition,然后从 BeanDefinition 中获得 beanClassName,最后通过反射初始化 beanClassName 的实例 instance。构造函数从 BeanDefinition 的 ...

    Spring bean 动态注册,jar包热替换

    spring的bean动态加载则需要对相应的bean进行动态注册,以及jar与class文件动态加载。测试示例中是spring boot 的部分代码,动态加载的内容为接口实现类,且初始化时加载本地的实现类,动态加载后改为非程序加载目录...

    Spring配置类解析(下)(csdn)————程序.pdf

    如果是,那么它们需要注册BeanDefinition。此外,Spring还会遍历配置类中的`BeanMethod`,即带有`@Bean`注解的方法,为每个方法生成对应的BeanDefinition。如果遇到方法重载,即相同类型的方法,Spring不会生成新的...

    扫描指定包下的class,并将javaBean对象动态注册到spring环境中

    一旦创建了`BeanDefinition`,就可以将其注册到`BeanDefinitionRegistry`,通常就是Spring的`DefaultListableBeanFactory`。 以下是一个简单的示例,展示了如何实现动态扫描和注册Bean: ```java ...

Global site tag (gtag.js) - Google Analytics