[Learning]《Spring源码深度解析》第六章笔记

0.What’s this?

这是一篇关于《Spring源码深度解析》的笔记

第六章 容器的功能扩展

除了XmlBeanFactory,Spring中还提供了另一个接口ApplicationContext,用于扩展BeanFactory的现有功能。

// 使用BeanFactory
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("xxx.xml"));
// 使用ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("xxx.xml");

6.1 设置配置路径

ClassPathXmlApplicationContext提供了一个方法setConfigLocations,支持将配置文件以数组的形式同时传入,解析给定的全部路径,如果数组中包含系统变量,会在内部调用resolvePath搜寻匹配的系统变量并进行替换。

6.2 扩展功能

通过refresh方法对配置文件做解析,并完成各种扩展功能的实现:

  1. prepareRefreh: 对系统属性或环境变量进行准备及验证,完成初始化前的准备工作
  2. obtainFreshBeanFactory: 初始化beanFactory,对XML文件进行读取
  3. prepareBeanFacory: 对BeanFactory进行各种功能填充,支持@Qualifier于@Autowired注解
  4. postProcessBeanFactory: 对子类覆盖的方法做额外处理
  5. invokeBeanFactoryPostProcessors: 激活各种BeanFactory的处理器
  6. registerBeanPostProcessors:注册拦截bean创建的bean处理器
  7. initMessageSource: 为上下文初始化Message源,对普通语言的消息体提供支持
  8. initApplicationEventMulticaseter: 初始化应用消息广播器,并放入applicationEventMulticaster中
  9. onRefresh: 留给子类来初始化其他bean
  10. registerListeners: 在所有注册的bean中查找listener bean,注册到消息广播器中
  11. finishBeanFacotryInitialization: 初始化剩下的非惰性单实例
  12. finishRefresh: 完成刷新,通知生命周期管理器刷新过程,并发出ContentRefreshEvent通知其他组件
  13. destoryBeans & cancelRefresh: 在以上步骤发生异常的情况下,删除创建的bean,并做取消刷新的后处理

6.3 环境准备

prepareRefresh方法对系统属性或环境变量进行准备及验证,完成初始化前的准备工作

  1. initPropertySources方法交给开发者根据需要进行重写(Spring 开放式架构涉设计)
  2. validateRequiredProperties方法对属性进行验证

6.4 加载BeanFactory

该方法的核心实现委托在refreshBeanFactory的实现中:

  1. 创建DefaultListableBeanFactory
  2. 指定序列化id
  3. 定制BeanFactory,提供对注解@Qualifier和@Autowired的支持
  4. 加载BeanDefinition
  5. 使用全局变量记录BeanFactory的实例

6.5 功能拓展

进入函数prepareBeanFactory之前,Spring已经完成了对配置的解析,ApplicationContext对功能的扩展在这里完成:

  1. 设置BeanFactory的classLoader为当前context的classLoader
  2. 设置BeanFactory的表达式语言处理器,以支持SpEL
  3. 为BeanFactory添加一个默认的propertyEdit,作为bean的属性等的设置管理工具
  4. 添加beanPostProcessor
  5. 设置忽略自动装配的接口
  6. 设置自动装配的特殊规则
  7. 增加对AspectJ的支持
  8. 添加默认的系统环境bean

6.5.1 SpEL语言的支持

SpEL(Spring Expression Language) 用于在运行时构建复杂表达式、存取对象图属性、对象方法调用。只依赖于core模块,可以单独使用。

SpEl的解析是在AbstractAutowireCapableBeanFactory.applyPropertyValues方法中,通过AbstractBeanFactory(基类)的evaluateBeanDefinitionString方法进行解析的。

6.5.2 增加属性注册编辑器

Spring 进行依赖注入时,能够把普通的属性注入进来,但是有些类型无法被识别,如Date类,在进行mapper转换时,它被认为是Date类,但在Xml配置文档中,它会被视为String类,从而抛出异常。此时有两种方式解决这个问题

1. 使用自定义属性编辑器

首先,通过继承PropertyEditorSupport类,实现一个属性编辑器,为一个Spring类型的值指定特殊的解析方法,将字符串解析为实际Bean所期望的类型,再通过setValue方法注入依赖。
然后再配置文件中,在bean标签内,通过class属性指定该Bean所使用的属性编辑器,将两者绑定。

2. 使用自带的属性编辑器

对于某些类,Spring提供了自带的属性编辑器,如Date类,可以使用Spring的CustomDateEditor类,绑定方式同上。具体处理过程略。

6.5.3 添加ApplicationContextAwareProcessor处理器

核心方法是invokeAwareInterfaces,实现了这些Aware接口的bean再被初始化后可以获得一些对应的资源。

6.5.4 设置忽略依赖

调用beanFactory.ignoreDependencyInterface(xxxx.class)设置Spring注入依赖时忽略这些类。

6.5.5 注册依赖

调用beanFactory.registerResolvableDependency(xxxx.class, this/beanFactory)设置Spring在注入依赖时添加这些类。

6.6 BeanFactory的后处理

6.6.1 激活注册的BeanFactoryPostProcessor

BeanFactoryPostProcessor接口于BeanPostProcessor相似,可以对bean的定义继续宁处理。IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其他bean之前读取配置元数据,并有可能修改。BeanFactoryPostProcessor可以配置多个,并且当BeanFactoryPostProcessor实现了Ordered接口时,可以通过order属性来指定执行次序。

1.PropertyPlaceholderConfigurer

用于处理在bean配置文件中出现的变量引用。该类是一个bean,有一个名为locations的列表属性,其中每一项的值是一个配置文件的位置,PropertyPlaceholderConfigurer将会扫描这些配置文件,从中查找符合条件的值来替换bean配置文件中的变量引用。

2.使用自定义BeanFactoryPostProcessor

自定义的BeanFactoryPostProcessor可以屏蔽一些不期望出现在bean中的属性值。定义一个bean,包含名为obscenties的属性,属性内为一个set标签包含一系列value子标签,value的内容即为需要屏蔽的内容。在postProcessorBeanFactory的实现中,可以通过重写StringValueResolver的resolverStringValue方法,将屏蔽词替换为其他字符串。最后将StringValueResolver设置到BeanDefinitionVisitor中即可。

3.激活BeanFactoryPostProcessor
  1. 对硬编码注册的后处理器进行处理,主要是通过AbstractApplicationContext中添加处理器方法addBeanFactoryPostProcessor进行添加。添加后的后处理器会存放在beanFactoryPostProcessor中,而在处理BeanFactoryPostProcessor是会先检测beanFactoryPostProcessor中是否有数据。
  2. 使用三个List记录后处理器:registryPostProcessors记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor类型的处理器、regularPostProcessor记录通过硬编码方式注册的BeanFactoryPostProcessor类型的处理器、registryPostProcessorBeans记录通过配置方式注册的BeanDefinitionRegistryPostProcessor类型的处理器。
  3. 对所有List中记录的后处理器统一调用postProcessBeanFactory方法
  4. 对beanFactoryPostProcessor中非BeanDefinitionRegistryPostProcessor类型的后处理器继续宁统一的postProcessorBeanFactory方法调用
  5. 处理普通beanFactory。

6.6.2 注册BeanPostProcessor

Spring中大部分功能都是通过后处理器进行扩展的,但是BeanFactory中其实并没有实现后处理器的自动注册,所以在调用的时候需要进行手动注册,而ApplicationContext中为其提供了自动注册功能,因此使用ApplicationContext方式获取bean时可以执行后处理器方法。

对于beanFactory中后处理器的注册,Spring支持对于BeanPostProcessor的排序,比如根据PriorityOrdered进行排序,根据Orderd进行排序或无序,而Spring在BeanPostProcessor的激活顺序上也会考虑进行排序。

6.6.3 初始化消息资源

Spring定义了访问国际化信息的MessageSource接口,并提供了几个易用的实现类。
消息资源的设置过程:

  1. 定义资源文件,如messages.properties设置英文或messages_zh_CN设置中文等。
  2. 定义配置文件,定义一个id为messageSource的bean,然后通过property内的list标签下的value子标签来定义消息。
  3. 使用ApplicationContext的getMessage方法获取消息。

6.6.4 初始化ApplicationEventMulticaster

Spring监听器的简单用法:

  1. 定义监听事件
  2. 定义监听器
  3. 添加配置文件
  4. 测试:发送事件,检查监听器的响应

当产生Spring时间的时候,会默认使用SimpleApplicationEventMulticaster的multicasterEvent来广播时间,遍历所有监听器,并使用监听器中的onApplicationevetn方法来进行监听器的处理。而对于每个监听器来说,其实都可以获取到产生的事件,但是是否进行处理则由事件监听器决定。

6.6.5 注册监听器

Spring注册监听器的时候所做的逻辑操作:

  1. 硬编码方式注册的监听器处理:直接将listener类加入监听器容器中
  2. 配置文件注册的监听器处理:将listener类的名字传递给addApplicationListenerBean方法,再由该方法获得bean并加入监听器容器中

6.7 初始化非延迟加载单例

完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。

6.7.1 ConversionService设置

类似于String转Date的方式,ConversionService提供了使用Converter来完成这一项工作:

  1. 定义转换器,即String如何变为Date类
  2. 注册转换器,在配置文件中定义id为conversonService的bean,通过name为converters的property下list标签内的bean子标签来指定converter类
  3. 测试,直接调用conversionService的convert方法。传入String和输出类的class对象,检验结果

6.7.2 冻结配置

冻结所有的bean定义,说明注册的bean定义将不被修改或进行任何进一步的处理。核心逻辑在freezeConfiguration方法内完成。

6.7.3 初始化非延迟bean的加载

ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化,提前实例化意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有的单例bean。该过程在finishBeanFactoryInitialization中完成。

6.8 finishRefresh

在Spring中还提供了LifeCycle接口,Lifecycle中包含start/stop方法。实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在关闭时调用stop方法结束生命周期,通常用来配置后台程序,在启动后一直运行。

  1. initLifecycleProcessor: 初始化LifecycleProcessor
  2. onRefresh:启动所有实现了Lifecycle接口的bean
  3. publishEvent:通过Spring中的事件发布机制来发出ContextRefreshedEvent事件,通知对应监听器做进一步处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值