`
游伯度
  • 浏览: 22799 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Spring IOC - BeanDefinition注册

阅读更多

上次分享中,提到了 Spring 把查找出来的资源加载解析成为 Document 对象,供后面的 BeanDefinition 注册使用。本次分享,就来看看 BeanDefinition 是如何注册的,以及他注册到什么地方。

 

1. 分析源码了解 BeanDefinition 的注册过程

  

1.1org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 创建 BeanDefinitionDocumentReader,默认创建是 DefaultBeanDefinitionDocumentReader
	BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
	documentReader.setEnvironment(this.getEnvironment());
	int countBefore = getRegistry().getBeanDefinitionCount();
	// resource 其实就是 ApplicationContext 实例
	documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
	return getRegistry().getBeanDefinitionCount() - countBefore;
}
// 你可以通过配置 documentReaderClass 属性来改变 BeanDefinitionDocumentReader 的实例
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
	return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
}
// 创建 XmlReaderContext 传递到 documentReader 上
protected XmlReaderContext createReaderContext(Resource resource) {
	if (this.namespaceHandlerResolver == null) {
		this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
	}
	// resouce 等信息设置到上下文中
	return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
			this.sourceExtractor, this, this.namespaceHandlerResolver);
}

通过上面的方法,初始准备了解析 Bean 定义需要的解析环境,把相关的解析需用的参数设置完成。其中有很重要的命名空间处理器(NamespaceHandlerResolver)会在后续的分享中讲解。

 

 

1.2 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

 

doRegisterBeanDefinitions方法是被registerBeanDefinitions调用的,完成注册工作转交给BeanDefinitionParserDelegate 的工作。

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	 // 设置上下文
	this.readerContext = readerContext;

	logger.debug("Loading bean definitions");
	// 获取 Document 根元素
	Element root = doc.getDocumentElement();

	// 执行注册操作
	doRegisterBeanDefinitions(root);
}

protected void doRegisterBeanDefinitions(Element root) {
	String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
	// 解析 profile 属性,判断是否需要注册此资源文件(spring3.0的新属性)
	if (StringUtils.hasText(profileSpec)) {
		Assert.state(this.environment != null, "environment property must not be null");
		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;
	// 在实例化的同时,需要检查 Bean 上面的初始化配置是否正确
	// BeanDefinitionParserDelegate#initDefaultsElement, BeanDefinitionParserDelegate)
	this.delegate = createHelper(readerContext, root, parent);

	preProcessXml(root);
	parseBeanDefinitions(root, this.delegate);
	postProcessXml(root);

	this.delegate = parent;
}

 

1.3 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

// 解析 Bean 定义的根节点,包含 import, alias, bean。
// Root 是解析的DOM根节点
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
	// 如果root 节点的namespace是空,或者是 http://www.springframework.org/schema/beans 
	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;
				// 和root节点的判断方式相同,如果是默认命名空间
				if (delegate.isDefaultNamespace(ele)) {
					parseDefaultElement(ele, delegate);
				}
				// 非默认命名空间,自定义节点
				else {
					delegate.parseCustomElement(ele);
				}
			}
		}
	}
	// 其他情况,说明是自定义节点
	else {
		delegate.parseCustomElement(root);
	}
}

 先看看默认命名空间的元素解析的入口:

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
	// 如果是 import 元素
	if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
		importBeanDefinitionResource(ele);
	}
	// 如果是 alias 元素
	else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
		processAliasRegistration(ele);
	}
	// 如果是 bean 元素
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	// 如果是嵌套的 beans 元素,递归解析
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		// recurse
		doRegisterBeanDefinitions(ele);
	}
}

 深入看看里面的具体实现,如果不关心这个里面的细节可以选择跳过。

/**
 * import 元素解析,根据配置的 resource 属性,再一次从资源查找入手,进行导入 bean 定义解析
 * Parse an "import" element and load the bean definitions
 * from the given resource into the bean factory.
 */
protected void importBeanDefinitionResource(Element ele) {
	// 获取 resource 属性
	String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
	if (!StringUtils.hasText(location)) {
		getReaderContext().error("Resource location must not be empty", ele);
		return;
	}

	// Resolve system properties: e.g. "${user.dir}"
	// 处理系统属性
	location = environment.resolveRequiredPlaceholders(location);

	// 记录真实的资源(用表达式配置的资源可能出现多个)
	Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

	// 判断是否是绝对路径
	// Discover whether the location is an absolute or relative URI 
	boolean absoluteLocation = false;
	try {
		absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
	}
	catch (URISyntaxException ex) {
		// cannot convert to an URI, considering the location relative
		// unless it is the well-known Spring prefix "classpath*:"
	}

	// Absolute or relative?
	// 如果是绝对路径,直接解析对应绝对路径的 Bean 定义资源就可以了
	if (absoluteLocation) {
		try {
			// 这个方法在前面资源装载中已经分享过, AbstractBeanDefinitionReader#loadBeanDefinitions(String, Set<Resource>) 
			int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
			if (logger.isDebugEnabled()) {
				logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
			}
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error(
					"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
		}
	}
	// 相对路径
	else {
		// No URL -> considering resource location as relative to the current file.
		try {
			int importCount;
			// 如果资源支持创建相对路径,则创建。
			Resource relativeResource = getReaderContext().getResource().createRelative(location);
			// 判断如果资源存在,进行解析
			if (relativeResource.exists()) {
				importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
				actualResources.add(relativeResource);
			}
			// 如果不存在,在拼一下绝对路径,进行解析。如果此时无法查找到资源,就会抛异常了
			else {
				String baseLocation = getReaderContext().getResource().getURL().toString();
				importCount = getReaderContext().getReader().loadBeanDefinitions(
						StringUtils.applyRelativePath(baseLocation, location), actualResources);
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
			}
		}
		catch (IOException ex) {
			getReaderContext().error("Failed to resolve current resource location", ele, ex);
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
					ele, ex);
		}
	}
	Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
	// 通知 import 元素已经解析完毕
	getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}

/**
 * 处理别名,或者说叫注册别名
 * Process the given alias element, registering the alias with the registry.
 */
protected void processAliasRegistration(Element ele) {
	String name = ele.getAttribute(NAME_ATTRIBUTE);
	String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
	boolean valid = true;
	if (!StringUtils.hasText(name)) {
		getReaderContext().error("Name must not be empty", ele);
		valid = false;
	}
	if (!StringUtils.hasText(alias)) {
		getReaderContext().error("Alias must not be empty", ele);
		valid = false;
	}
	if (valid) {
		try {
			// 注册到别名Map中,后面会再次提到此处的使用
			getReaderContext().getRegistry().registerAlias(name, alias);
		}
		catch (Exception ex) {
			getReaderContext().error("Failed to register alias '" + alias +
					"' for bean with name '" + name + "'", ele, ex);
		}
		getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
	}
}

/**
 * 处理 bean 元素,本身不处理,交给了 BeanDefinitionParserDelegate 
 * Process the given bean element, parsing the bean definition
 * and registering it with the registry.
 */
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	// 解析Bean定义,存放在 BeanDefinitionHolder 中
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		// 判断是否需要装饰 BeanDefinition,如果需要装饰,返回装饰后的 Bean 定义
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			// Register the final decorated instance.
			// 注册 Bean 到 Factory
			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));
	}
}

BeanDefinitionHolder

BeanDefinitionHolder  不仅包含了 BeanDefinition 信息,同时记录了对应的Bean的名称以及别名信息。

 

1.4 org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element, BeanDefinition)

BeanDefinitionParserDelegate解析 Bean 定义的地方。

 

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
	// id 属性
	String id = ele.getAttribute(ID_ATTRIBUTE);
	// name 属性,可以用“,;”分割,得到别名定义
	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));
	}

	// bean 的唯一名称是定义的 id 属性,不是name
	// 如果当没有定义 id 属性时,从定义的别名中取得一个
	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");
		}
	}

	// 如果不是嵌套bean,验证 beanName 唯一性
	if (containingBean == null) {
		checkNameUniqueness(beanName, aliases, ele);
	}

	// 解析 bean 属性值以及子元素标签
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
		if (!StringUtils.hasText(beanName)) {
			try {
				// 如果是内部 bean,创建内部 bean 名称
				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);
		// 返回 BeanDefinitionHolder
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}

	return null;
}
 
1.5 org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#decorateIfRequired

如果自定义的 schema 来进行 Bean 解析,调用对应的 NameSpaceHandler 进行装饰。具体的自定义方式、方法、原理将在下次分享中分享。

private BeanDefinitionHolder decorateIfRequired(
		Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
	// 获取对应的命名空间,如果不是 Spring 定义的默认命名空间,进行装饰处理
	String namespaceUri = getNamespaceURI(node);
	if (!isDefaultNamespace(namespaceUri)) {
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler != null) {
			return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
		}
		else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
		}
		else {
			// A custom namespace, not to be handled by Spring - maybe "xml:...".
			if (logger.isDebugEnabled()) {
				logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
			}
		}
	}
	return originalDef;
}

 

 

1.6 org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(Element, BeanDefinition)

 

解析自定义 schema 中的 bean 元素,进行自定义解析

public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
	String namespaceUri = getNamespaceURI(ele);
	// 获取对应的命名空间解析处理器来进行解析处理
	NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
	if (handler == null) {
		error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
		return null;
	}
	// 解析的实现中选择是否需要把bean定义注册到 Factory 中
	return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}

 

1.7 org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition

 

此法静态方法,负责把解析好的 Bean 定义注册到容器中

public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// Register bean definition under primary name.
	String beanName = definitionHolder.getBeanName();
	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,我们看看 Bean 注册是怎么实现的:

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
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) {
		// 所有解析好的 Bean 定义都会放在 beanDefinitionMap 中
		Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		// 如果可以通过 Bean 名称获取到 Bean 定义,那么需要判断是否允许覆盖
		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;
		}
		// 注册 Bean 定义到 beanDefinitionMap 中
		this.beanDefinitionMap.put(beanName, beanDefinition);

		resetBeanDefinition(beanName);
	}
}

 

综上,所有解析好的 Bean 定义被封装在 BeanDefinitionHolder 中,让后经过各种判断最终放在了 DefaultListableBeanFactory 的 benDefinitionMap 中。至此,Bean 解析和注册完成,为后续的依赖注入提供了数据基础。下次分享还是要深化这个解析过程,讲述自定义 schema 解析Bean过程。

 

OK,今天就到这里吧。

分享到:
评论

相关推荐

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

    总结来说,BeanDefinition是Spring IoC容器的核心组成部分,它封装了bean的所有配置信息,使容器能够根据这些信息实例化、配置、管理bean,从而实现了控制反转。通过XML配置文件,我们可以轻松地定义bean及其属性,...

    springIoc实现原理

    1. **读取配置**:Spring容器读取XML、Java配置或基于注解的配置信息,构建BeanDefinition对象,其中包含了对象的类名、属性、依赖等信息。 2. **Bean实例化**:根据BeanDefinition,Spring容器创建Bean实例,可以是...

    spring ioc

    1. `BeanDefinition`:每个 Bean 在容器中都有一个对应的 `BeanDefinition`,它存储了 Bean 的所有元数据,如类名、初始化方法、依赖等。 2. `BeanFactory`:这是最基础的 Bean 容器接口,负责创建和管理 Bean。 3. ...

    Spring IoC源码深度剖析开源架构源码2021.pdf

    - 在Spring的XML配置中,定义的每一个`&lt;bean&gt;`标签都会被解析成一个`BeanDefinition`对象。 - `BeanDefinition` 对象包含了一系列属性,这些属性来自`&lt;bean&gt;`标签的属性配置,例如 `class` 属性与 `...

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

    IoC 容器中存放的是 Bean 的定义即 BeanDefinition,BeanDefinition 接口中包含了这个类的 Class 信息以及是否是单例等。那么如何从 BeanDefinition 中实例化出 Bean 对象呢? BeanFactory 中 getBean 的主体思路是...

    Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程.doc

    通过设置资源解析器和环境、设置配置路径、初始化 BeanFactory、加载 Bean 定义资源、解析 Bean 定义资源和注册 BeanDefinition,这些步骤组成了 IOC 初始化流程。 在 Spring 框架中,IOC 容器是核心组件,负责管理...

    spring-framework-reference-4.3.19.pdf

    - **Groovy Bean Definition DSL**:Spring 4.0引入了Groovy DSL来定义Bean配置,提供了一种更简洁、更易于阅读的方式。 - **核心容器改进**:包括BeanFactory后处理器的增强、更强大的Bean工厂功能等。 - **Web改进...

    Spring中眼花缭乱的BeanDefinition.docx

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

    spring ioc以及事物架构图

    - **BeanDefinitionDocumentReader**:读取XML文档中的Bean定义,并将其解析为BeanDefinition对象。 - **ResourceEntityResolver**:用于解析资源实体。 - **ResourceLoader**:负责加载各种类型的资源。 - **...

    模拟Spring的IOC

    - `registerBeanDefinition(String beanId, BeanDefinition beanDefinition)`: 注册一个Bean定义。 - `getBean(String beanId)`: 根据beanId获取Bean实例。 - `initializeBean(String beanId)`: 初始化Bean,包括...

    Spring IOC设计原理解析.docx

    Spring的IOC体系主要由BeanFactory和BeanDefinition组成。BeanFactory是Spring容器的基础接口,负责管理和实例化Bean。BeanDefinition则存储了Bean的元数据,如类名、属性、依赖等信息。 三、IoC容器的初始化 1. `...

    官方原版源码spring-framework-5.2.3.RELEASE.zip

    `spring-5.2.3.RELEASE-schema.zip`包含了Spring的XML配置文件的XSD(XML Schema Definition)定义。这些定义文件规定了我们在Spring XML配置文件中可以使用的元素和属性,帮助我们编写符合规范的配置。通过查看这些...

    手写spring ioc(三) 资源org.zip

    在"org"这个文件夹中,可能包含了实现这些功能的类,如BeanDefinition用于存储bean的定义信息,BeanFactory作为bean的工厂,AutowiredAnnotationBeanPostProcessor处理自动注入的注解,以及可能的容器接口实现类等。...

    Spring 5.2.9的IOC核心jar包

    `BeanDefinition`则存储了Bean的配置信息。 **源码分析** 对于学习和理解Spring框架,查看源码是很有帮助的。你可以深入研究这些jar包中的类和方法,了解Spring如何管理Bean,如何解析配置,以及如何执行依赖注入等...

    Spring IOC源码解读

    BeanDefinition是Spring中用于描述Bean实例的关键数据结构,包含了Bean的属性、依赖对象、构造器参数等信息。而ApplicationContext则是一种更高级的容器,除了提供BeanFactory的基本功能外,还增加了许多面向框架的...

    spring-framework-5.2.0.RELEASE-master.zip

    同时,对于`BeanDefinition`、`BeanPostProcessor`等关键接口的注释,能帮助我们深入理解bean的生命周期。 **源码解析**: 源码解析部分通常会详细解释Spring的各个组件和模块是如何协同工作的。例如,解析`...

    spring ioc+mvc代码

    我们可以通过`BeanDefinition`类来表示这些信息。当容器启动时,会根据定义创建bean实例。 1.3 依赖注入(Dependency Injection,DI) DI是IOC的一种实现方式,通过容器将依赖关系注入到对象中,而不是由对象自行...

    Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计.doc

    BeanRegistry是另一个关键组件,它允许手动向IoC容器注册BeanDefinition对象。BeanDefinition包含了Bean的所有元数据,如类名、依赖关系、初始化方法等。注册过程是IoC容器填充Bean实例的前提。 在更高级别的设计中...

    【Java面试】介绍下Spring IoC的工作流程.doc

    - **BeanDefinition的生成与注册**:Spring容器在启动时会解析这些声明,生成对应的BeanDefinition对象。BeanDefinition包含了Bean的类信息、属性、依赖关系等元数据。所有BeanDefinition会被保存在一个内部Map中,...

    深入解析Spring IoC源码:核心机制与实践应用

    5. **BeanDefinition注册**:配置类被解析并注册为BeanDefinition,这样容器就知道了需要管理哪些Bean。 6. **容器刷新**:最后,调用`refresh()`方法,执行一系列初始化操作,包括调用`...

Global site tag (gtag.js) - Google Analytics