啃啃老菜:
Spring
IOC核心源码学习(一)
本文主要以
spring ioc
容器基本代码骨架为切入点,理解
ioc
容器的基本代码组件结构,各代码组件细节剖析将放在后面的学习文章里。
关于IOC容器
IoC
容器:最主要是完成了完成对象的创建和依赖的管理注入等等。
先从我们自己设计这样一个视角来考虑:
所谓控制反转,就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们可配置的文件。
对象和对象关系怎么表示?
可以用
xml
,
properties
文件等语义化配置文件表示。
描述对象关系的文件存放在哪里?
可能是
classpath
,
filesystem
,或者是
URL
网络资源,
servletContext
等。
回到正题,有了配置文件,还需要对配置文件解析。
不同的配置文件对对象的描述不一样,如标准的,自定义声明式的,如何统一?
在内部需要有一个统一的关于对象的定义,所有外部的描述都必须转化成统一的描述定义。
如何对不同的配置文件进行解析?需要对不同的配置文件语法,采用不同的解析器。
基于以上问题,对应过来,刚好是
spring ioc
容器抽象的的几个主要接口:
Resource
BeanDefinition
BeanDefinitionReader
BeanFactory
ApplicationContext
以上五个都是接口,都有各式各样的实现,正是这
5
个接口定义了
spring ioc
容器的基本代码组件结构。而其组件各种实现的组合关系组成了一个运行时的具体容器。下面来逐步了解各个组件的信息。
各代码组件详解
1.Resource
是对资源的抽象,每一个接口实现类都代表了一种资源类型,如
ClasspathResource
、
URLResource
,
FileSystemResource
等。每一个资源类型都封装了对某一种特定资源的访问策略。它是
spring
资源访问策略的一个基础实现,应用在很多场景。

具体可以参考文章
:
Spring
资源访问剖析和策略模式应用
http://www.ibm.com/developerworks/cn/java/j-lo-spring-resource/index.html
2.BeanDefinition
用来抽象和描述一个具体
bean
对象。是描述一个
bean
对象的基本数据结构。
3.BeanDefinitionReader
BeanDefinitionReader
将外部资源对象描述的
bean
定义统一转化为统一的内部数据结构
BeanDefinition
。对应不同的描述需要有不同的
Reader
。如
XmlBeanDefinitionReader
用来读取
xml
描述配置的
bean
对象。

4.BeanFactory
用来定义一个很纯粹的
bean
容器。它是一个
bean
容器的必备结构。同时和外部应用环境等隔离。
BeanDefinition
是它的基本数据结构。它维护一个
BeanDefinitions Map,
并可根据
BeanDefinition
的描述进行
bean
的创建和管理。

5.ApplicationContext
从名字来看叫应用上下文,是和应用环境息息相关的。没错这个就是我们平时开发中经常直接使用打交道的一个类,应用上下文,或者也叫做
spring
容器。其实它的基本实现是会持有一个
BeanFactory
对象,并基于此提供一些包装和功能扩展。为什么要这么做呢?因为
BeanFactory
实现了一个容器基本结构和功能,但是与外部环境隔离。那么读取配置文件,并将配置文件解析成
BeanDefinition
,然后注册到
BeanFactory
的这一个过程的封装自然就需要
ApplicationContext
。
ApplicationContext
和应用环境细细相关,常见实现有
ClasspathXmlApplicationContext,FileSystemXmlApplicationContext,WebApplicationContext
等。
Classpath
、
xml
、
FileSystem
、
Web
等词都代表了应用和环境相关的一些意思,从字面上不难理解各自代表的含义。
当然
ApplicationContext
和
BeanFactory
的区别远不止于此,有:
1.
资源访问功能:在
Resource
和
ResourceLoader
的基础上可以灵活的访问不同的资源。
2.
支持不同的信息源。
3.
支持应用事件:继承了接口
ApplicationEventPublisher
,这样在上下文中为
bean
之间提供了事件机制。
……

以上
5
个组件基本代表了
ioc
容器的一个最基本组成,而组件的组合是放在
ApplicationContext
的实现这一层来完成。
以ClasspathXmlApplicationContext 容器实现为例,其组合关系如下:

ClassPathXmlApplicationContext的refresh() 方法负责完成了整个容器的初始化。
为
什么叫refresh?也就是说其实是刷新的意思,该IOC容器里面维护了一个单例的BeanFactory,如果bean的配置有修改,也可以直接调用
refresh方法,它将销毁之前的BeanFactory,重新创建一个BeanFactory。所以叫refresh也是能理解的。
以下是Refresh的基本步骤:
1.把配置xml文件转换成resource。resource的转换是先通过ResourcePatternResolver来解析可识别格式的配置文件的路径
(如"classpath*:"等),如果没有指定格式,默认会按照类路径的资源来处理。
2.利用XmlBeanDefinitionReader完成对xml的解析,将xml Resource里定义的bean对象转换成统一的BeanDefinition。
3.将BeanDefinition注册到BeanFactory,完成对BeanFactory的初始化。BeanFactory里将会维护一个BeanDefinition的Map。
当getBean的时候就会根据调用BeanFactory,根据bean的BeanDifinition来实例化一个bean。当然根据bean的lazy-init、protetype等属性设置不同以上过程略有差别。
refresh()代码如下:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
beanFactory.destroySingletons();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
}
}
以上的obtainFreshBeanFactory是很关键的一个方法,里面会调用loadBeanDefinition方法,如下:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
LoadBeanDifinition方法很关键,这里特定于整个IOC容器,实例化了一个XmlBeanDefinitionReader来解析Resource文件。关于Resource文件如何初始化和xml文件如何解析都在
loadBeanDefinitions(beanDefinitionReader);
里面的层层调用完成,这里不在累述。
小结
Spring
的扩展性是毋庸置疑的,学习
spring
的设计是一个很好的实践理论结合。主要个人觉得有几点:
1.
框架顶层的设计有着很好的抽象,遵循面向接口编程的规范。
Resource
、
BeanFactory
、
ApplicationContext
都是非常好的接口抽象,非常明确的定义了该组件的一些功能。
2.
利用组合模式。
3.
个组件的实现里大量使用了模板方法模式,提升了同一组件代码的复用性。
4.
各种设计保留了扩展的接口,很多基于
spring
的框架都可以很容易的介入实现了自己的一些扩展。
5.
框架里采用里很多经典的设计模式,如代理、装饰、策略等等。

- 大小: 17 KB

- 大小: 13.7 KB

- 大小: 20.6 KB

- 大小: 22.6 KB

- 大小: 55.8 KB
分享到:
相关推荐
* 学习成本高:Spring IOC 的学习成本较高,需要开发者具备一定的编程经验和知识。 * 配置复杂:Spring IOC 的配置相对复杂,需要开发者具备一定的经验和知识。 Spring IOC 是 Spring Framework 中的一种核心组件,...
spring-core:核心模块 依赖注入IOC和DI的最基本实现 spring-beans:Bean工厂与装配 spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和...
总结起来,"实验一:Spring IoC中Bean的装置的jar包"涉及了Spring框架的核心概念,包括Bean、IoC、配置方式(XML、Java配置、注解)以及Bean的生命周期和作用域。理解并熟练掌握这些知识点,对于提升Spring应用的...
Spring Ioc(Inversion of Control,控制反转)是Spring框架的核心特性之一,它改变了传统应用程序中对象的创建和管理方式。在传统的软件设计中,对象的创建和依赖关系的维护通常由代码自身来完成,而在Spring Ioc中...
标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...
《Spring IOC核心技术》是冰河原创的一本专注于Spring IOC核心概念和技术的电子书。Spring作为Java开发领域的重要框架,它的依赖注入(IOC)机制是其核心功能之一,它极大地简化了对象之间的耦合,提高了代码的灵活...
总的来说,Spring IOC的学习涉及了Java面向对象编程、设计模式、反射机制等多个领域,结合源码分析可以让我们更好地理解和利用这一强大的功能。通过阅读`javaspring`中的源码示例,我们可以将理论知识与实践相结合,...
IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 优点 1. 简化对象的创建:IoC ...
Spring IOC,即Inversion of Control(控制反转),是Spring框架的核心特性之一,它负责管理和装配应用程序中的对象。在传统的编程模式中,对象通常自行创建和管理它们所依赖的其他对象,这导致了代码间的高耦合。而...
2. **依赖注入(DI)**:Spring IOC的主要功能之一就是依赖注入。有两种方式实现DI:构造器注入和setter注入。构造器注入是在Bean实例化时通过构造函数传递依赖,而setter注入则是通过调用setter方法设置依赖。在`...
Spring 框架是Java开发中的核心框架,它主要由两个关键部分组成:IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。这两个概念是Spring框架的核心特性,极大地简化了企业...
Spring框架的核心功能之一便是依赖注入(Dependency Injection, DI),而这一功能主要通过IoC容器来实现。在Spring框架中,IoC容器负责管理应用对象的生命周期、配置和装配。简单来说,IoC容器就是一个工厂,它可以...
Spring框架是Java开发中不可或缺的一部分,它主要由两个核心组件构成:IoC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。本笔记将深入探讨这两个概念以及它们在Spring中...
Spring IoC,全称为Inversion of Control,即控制反转,是Spring框架的核心特性之一。它是一种设计模式,改变了传统程序中的对象创建和管理的方式,将对象的生命周期管理交由Spring容器来负责,使得代码更加解耦,...
Spring4 IOC(Inversion of Control,控制反转)是Spring框架的核心特性之一,它极大地简化了Java应用程序的开发。在这个示例源码中,我们可以深入理解并学习如何在实际项目中运用Spring的IOC容器来管理对象的生命...
6. **自动装配**:Spring提供了一种自动装配Bean依赖的方式,可以通过`@Autowired`注解实现。此外,还可以通过`@Qualifier`注解来指定具体要注入哪个Bean。 7. **基于注解的配置**:随着Java 5的发布,Spring引入了...
Spring IOC,全称为Inversion of Control,即控制反转,是Spring框架的核心特性之一。它将对象的创建和管理从应用程序代码中分离出来,使得应用程序不再负责对象的生命周期,而是由Spring容器来负责。这种设计模式...
AOP(面向切面编程)**:Spring的另一个核心特性,与IOC紧密相关,可以用来实现日志、事务、权限控制等功能,通过定义切面、通知和切入点表达式实现代码的解耦。 以上只是Spring IOC的一部分知识点,实际上还包括...
2. **依赖注入**:Spring IoC容器根据配置文件中的信息,动态地将依赖关系注入到bean中。有两种方式实现依赖注入:构造器注入和setter注入。构造器注入是在bean实例化时通过构造函数传递依赖,而setter注入则是通过...
这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得...