Spring基础之IOC和AOP系列(2)
啥是IOC?
所谓的IOC也就是控制反转,也就是Bean的创建权利交给了Spring中IOC容器。本来我们在创建对象的过程中是直接去new一个对象来创建一个Bean,也可以这样理解,而现在把这个new的权利交给了Spring的IOC容器,这个也就是所谓的控制反转。既然IOC容器可以创建,但是创建的Bean与·Bean之间的关系,IOC容器如何知道。这个就要求文件。
那么依赖注入呢?
DI(Dependency Injection)依赖注入:指的是Bean被动接受依赖类,而不是让他自己去找。而是创建的过程中,如果对某个Bean有依赖,那么这个被依赖的Bean会被依赖它的Bean被动接受(也就是不管接受不接受都得接受)。
管理Bean的创建过程的是IOC的这个对象BeanFactory;
BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于管理Bean的一个工厂。在Spring中,BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
最终的默认实现类是DefaultListableBeanFactory,他实现了所有的接口;
BeanDefinition
SpringIOC 容器管理了我们定义的各种 Bean 对象及其相互的关系,Bean 对象在 Spring 实现中是以 BeanDefinition 来描述的。
BeanDefinition定义了Bean的数据结构,用来存储Bean。
3.ApplicationContext
ApplicationContext实现了最顶层的BeanFactory接口,也是一个IOC容器,ApplicationContext作为Spring的启动入口,也是IOC容器初始化的入口
3.IOC容器初始化
IOC 容器的初始化包括BeanDefinition 的 Resource 定位、载入和注册这三个基本的过程
1.super(parent)方法 设置 Spring 的资源加载器
private final ResourceLoader resourceLoader;
2.setConfigLocations() 把配置文件路径存放到数组中(可传入多个参数路径)
private String[] configLocations;
3.refresh() 把所有的Bean重新构造一遍
4.obtainFreshBeanFactory() Bean 定义资源文件的载入(从这个方法开始)
5.refreshBeanFactory() 使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法,具体实现调用子类容器refreshBeanFactory()方法,
子类refreshBeanFactory()
判断 BeanFactory 是否存在,如果存在则先销毁 beans 并关闭 beanFactory,接着
创建 DefaultListableBeanFactory,并调用 loadBeanDefinitions(beanFactory)装载 bean 定义。
5.1.createBeanFactory() 用createBeanFactory对beanFactory工厂初始化 newDefaultListableBeanFactory(getInternalParentBeanFactory())表示所有Bean都是由DefaultBeanFactory()创建.
DefaultBeanFactory的类结构图
6.loadBeanDefinitions(beanFactory) 调用载入Bean定义的方法,主要这里又使用了一个委派模式,在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
6.1.newXmlBeanDefinitionReader(beanFactory) 创建Bean读取器,并通过回调设置到容器中去,容器使用该读取器读取Bean定义资源
7.loadBeanDefinitions(beanDefinitionReader) 传入新建的读取器 Bean读取器真正实现加载的方法
7.1.getConfigResources(); 获取Bean定义资源的定位 即2中保存的参数String[] configLocations;
8.reader.loadBeanDefinitions(configLocations); XmlBean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源
9.loadBeanDefinitions(location) 是一个重载方法
10.loadBeanDefinitions(location, null)(重载方法) 获取在IoC容器初始化过程中设置的资源加载器 一1中设置的resourceLoader; 判读是否为NULL,并且如果 resourceLoader instanceof ResourcePatternResolver
11.loadBeanDefinitions(resources) 委派设计模式委派给XmlBeanDefinitionReader实现
12.doLoadBeanDefinitions()(重载方法) 将读入的XML资源进行特殊编码处理 载入XML形式Bean定义资源文件方法
首先/将资源文件转为InputStream的IO流 在从InputStream中得到XML的解析源
13.doLoadBeanDefinitions()(重载方法) 从特定XML文件中实际载入Bean定义资源的方法
14.doLoadDocument() 将XML文件转换为DOM对象,解析过程由documentLoader实现
15.registerBeanDefinitions() 这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
16.documentReader.registerBeanDefinitions 解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口, 具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成
17.doRegisterBeanDefinitions(root) do开头的都是干活的方法,开始解析Bean
18.preProcessXml(root) 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
19.parseBeanDefinitions() 进入了加载过程 解析过程解析Bean.xml中的标签 ,把xml中的内容变成BeanDefinition 运用 delegate委派模式
20.parseDefaultElement(ele, delegate) 使用Spring的Bean规则解析元素节点
21.processBeanDefinition(ele, delegate) 进入注册环节
22.BeanDefinitionReaderUtils.registerBeanDefinition() 向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口 进入注册环节
Key就是Bean id value为BeanDefinition
23.registry.registerBeanDefinition() 向IOC容器注册BeanDefinition
存贮到ConcurrentHashMap中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
总体流成:首先把需要加载的Bean.xml路径存放到数组中,在创建一个DefaultListableBeanFactory()容器,获取路径把路径下的XML文件转化成java文件,把java文件解析成BeanDefinition,在把BeanDefinition存储到ConcurrentHashMap中。