引入
spring众所周知的一个特性是IOC,控制翻转,意义就是将原本需要我们手动去维护的:Bean的依赖关系、创建销毁等生命周期,放到spring容器中去执行,让容器去管理这一系列的运行时环境,以保存各个对象的状态。
在分析spring的源码之前,我们先来看spring是如何使用的。通常我们的项目中会有着大量配置文件,而真正的核心配置有哪些?
先来实现一个最简单的demo:
1.定义一个类
package example.controller;
public class Cat {
public String name = "aaa";
}
2.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="cat" class="example.controller.Cat"></bean>
</beans>
3.入口函数
public class MainTest {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
Cat cat = ac.getBean(Cat.class);
System.out.println(cat.name);
}
}
到此,运行main函数,就可以成功输出预期的“aaa”。
由此看来,这段代码中spring的功能可以被概括为:
- ClassPathXmlApplicationContext(“spring/applicationContext.xml”)
读取配置xml文件,解析各个标签,然后保存在内存中 - ac.getBean(Cat.class)
根据保存的配置文件中的信息,进行Bean的实例化 - 调用实例化后的对象,实现整个逻辑的串联
问题
- 什么是ApplicationContext?
ApplicationContext可以被翻译为 应用上下文 。
spring众所周知的一个特性是IOC,控制翻转,意义就是将原本需要我们手动去维护的:Bean的依赖关系、创建销毁等生命周期,放到spring容器中去执行,让容器去管理这一系列的运行时环境,以保存各个对象的状态。
spring容器的根接口是BeanFactory,这个接口提供了IOC的基本实现,提供了Bean的创建、依赖注入等基本操作;而ApplicationContext接口,是BeanFactory的一个扩展,它不仅继承了BeanFactory接口,还继承了MessageSource, ApplicationEventPublisher, ResourcePatternResolver等一系列接口,可以说是给spring容器提供了一个支持更丰富功能的上下文环境。 - xml中的配置如何被解析,并加载到内存中?
资源文件首先被封装为Resource,然后获取对Xml文件的验证模式(DTD与XSD);加载xml文件,得到对应的Document;根据返回的Document提取并且注册Bean Definition。这个过程不进行详细地分析了。
这里有一个重要的定义:Bean Definition,我们在Bean的加载阶段代码中会经常看到它。Bean Definition顾名思义Bean定义,是spring用来描述Bean的一个类,包括bean对象的class类型、依赖关系、是否自动装配等。可以说,它保存了从XML解析出来的Bean的一系列信息。
总之这个步骤也就是将bean 从配置文件加载到内存中 的过程。其中的解析xml有两种方式:默认形式(包括4个标签import、bean、context、alias),自定义形式。
在解析到内存的过程中用到两个缓存:
beanDefinitionNames:存储beanName
beanDefinitionMap:存储beanName与BeanDefinition的映射map
本系列spring分析分为两部分
- Bean的加载
以BeanFactory的getBean方法为入口,整理Bean的加载流程。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
- ApplicationContext容器的系列扩展功能
将以ClassPathXmlApplicationContext的构造方法为入口,整理spring加载Bean之外的额外功能。
/**
* Create a new ClassPathXmlApplicationContext with the given parent,
* loading the definitions from the given XML files.
* @param configLocations array of resource locations
* @param refresh whether to automatically refresh the context,
* loading all bean definitions and creating all singletons.
* Alternatively, call refresh manually after further configuring the context.
* @param parent the parent context
* @throws BeansException if context creation failed
* @see #refresh()
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
参考:一篇非常优秀的spring源码解读
https://blog.csdn.net/v123411739/article/details/85934686