1.Spring容器技术内幕
spring容器比作一辆汽车,可以将BeanFactory看作汽车的发动机,而ApplicationContext则是一辆完整的汽车,但是它不包括发动机、离合器,等其他组件。在ApplicationContext内,各个组件按部就班,有条不紊地完成汽车的各项功能
1.1 BeanFactory和ApplicationContext简介
// Bean工厂是Spring框架最核心的接口,提供了高级Ioc的配置机制,使管理不同的java对象成为可能,所有可以被Spring容器实例化并管理的Java类都可以成为Bean(一般称BeanFactory为Ioc容器)
org.springframework.beans.factory.BeanFactory
// 应用上下文建立在BeanFactory基础之上,提供了更多面向应用的可能,易于创建实际应用。(一般称ApplicationContext为应用上下文,其实也可以成为容器)
org.springframework.context.ApplicationContext
// BeanFactory是spring框架的基础设施,面向的是spring本身
// ApplicationContext面向使用Spring框架的开发者
1.2 BeanFactory的类体系结构
1.2.1 BeanFactory的常用方法
最主要的方法就是getBean(String beanName),该方法从容器中返回特定名称的Bean,BeanFactory的功能通过其他的接口得到不断拓展
1.2.2 BeanFactory的类图结构
ListableBeanFactory:定义访问容器中Bean基本信息的方法
HierarchicalBeanFactory: 父子级联Ioc容器的接口
ConfigurableBeanFactory: 一个重要接口,增强了Ioc容器的可定制性。定义了设置类装载器,属性编辑器,容器初始化后置处理器等方法
SingletonBeanRegistry: 定义了允许在运行期将容器中注册单实例Bean
BeanDefinitionRegistry: 提供了向容器中手工注册BeanDefinition对象的方法(registerBeanDefinition)
1.3 ApplicationContext类体系结构
如果说BeanFactory是Spring的”心脏“,nameApplicationContext就是完整的”身躯“了。 ApplicationContext由BeanFactory派生而来
ApplicationContext的主要实现类是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,接口功能如下:
ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能
MessageResource: 为应用提供il8国际化消息访问的功能
ResourcePatternResolver: 可以通过带前缀的Ant风格的资源文件路径装载Spring的配置文件
LifeCycle:该接口提供start()和stop()两种方法,用于控制异步处理过程,该接口会降start/stop的信息传递给容器中所有实现了该接口的Bean,以达到管理和控制JMX、任务调度等目的。
ConfigurableApplicationContext: 拓展于ApplicationContext,新增了两个方法refresh()和close(),让ApplicationContext具有启动、刷新和关闭应用上下文的能力。
1.4 内部工作机制
spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该方法的refresh()方法定义了Spring容器在加载配置文件后的各项处理过程
AbstractApplicationContext#refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
// ①初始化BeanFactory
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
// ② 调用后工厂处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
// ③ 注册Bean后处理器
this.registerBeanPostProcessors(beanFactory);
// ④ 初始化消息源
this.initMessageSource();
// ⑤ 初始化应用上下文事件广播器
this.initApplicationEventMulticaster();
// ⑥ 初始化其他特殊的Bean,由具体子类实现
this.onRefresh();
// ⑦ 注册事件监听
this.registerListeners();
// ⑧ 调用后工厂处理器
this.finishBeanFactoryInitialization(beanFactory);
// ⑨ 完成刷新并发布容器刷新事件
this.finishRefresh();
} catch (BeansException var9) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var9);
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
Spring容器从加载配置文件到创建出一个完整Bean的作业流程及其参与的角色
1.4.1 BeanDefinition
org.springframework.beans.factory.config.BeanDefinition是配置文件元素标签在容器中的内部表示,元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit类属性
BeanDefinition的类结构图如下:
Spring通过BeanDefinition将配置文件中的配置信息转换为容器的内部表示,并将这些BeanDefinition注册到BeanDefinitionRegister中。一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或者重启。
利用容器中注册的BeanFactoryPostPorcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,得到成品的BeanDefinition
1.4.2 InstantitationStrategy
org.springframework.beans.factory.support.CglibSubclassingInstantiationStrategy负责根据BeanDefinition对象创建一个Bean实例,接口的设计是考虑到后续可以方便的采用不同的实例化策略,以满足不同的应用需求。
SimpleInstantiationStrategy是最常用的实例化策略,仅负责实例化Bean的操作,相当于执行java语言中的new的功能,它并不会参与Bean属性的设置工作。所以由InstantiationStrategy返回回来的Bean实例实际上是一个半成品的Bean实例,属性填充的工作由BeanWrapper来完成
1.4.3 BeanWrapper(美[ˈræpər] 英[ˈræpə®])
org.springframework.beans.BeanWrapper相当于一个代理器,Spring委托BeanWrapper完成Bean属性的填充工作,在Bean实例被InstantiationStrategy创建出来后,通过调用BeanWrapper#setWrappedInstance方法完成属性填充。
1.5 容器事件
背景:Spring的ApplicationContext能够发布事件并且允许注册相应的事件监听器,因此它拥有一套完善的事件发布和监听机制,java通过java.util.EventObject类和java.util.EventListener接口描述事件和监听器,除了事件和监听器外,还有另外三个比较重要的概念:
事件源:事件的产生者,任何一个EventObject都必须拥有一个事件源
事件监听注册表:组件或者框架的保存地方,用来保存事件监听器。
事件广播器:事件和事件监听器沟通的桥梁,负责把事件通知给事件监听器。
1.5.1 Spring事件类结构
1.事件类
ApplicationEvent的唯一构造函数是ApplicationEvent(Object Source),通过source指定事件源,它有两个子类。
ApplicationContextEvent:容器事件,它拥有4个子类,表示容器启动,刷新,停止及关闭
RequestHandlerEvent:这是与Web应用相关的事件,当一个http请求被处理后,产生该事件
2.事件监听器接口
Spring的事件监听器都继承自ApplicationListener接口
可以看到ApplicationListener接口只定义了一个方法,该方法接收ApplicationEvent事件对象,其中SmartApplicationListener接口是Spring3.0新增的,它定义了两个方法,
第一个方法指定监听器支持那种类型的容器事件,它只会对该类型的事件做出反应
第二个方法指定监听器仅对何种事件源对象做出相应
其中GenericApplicationListener接口是Spring4.2新增的,该接口增强了对泛型事件类型的支持,不仅限于ApplicationEvent子类型,而是采用可解析的ResolvableType,它定义了两个方法:
第一个方法用于判断指定监听器是否支持给定的事件类型
第二个方法用于判断监听器是否支持所给定的事件源对象
3.事件广播器
当发生容器事件时,容器主控程序将调用事件广播器将事件通知给事件监听器注册表中的事件监听器,事件监听器分别对事件进行响应。Spring为事件广播器定义了接口,并提供了实现类
1.5.2 Spring事件体系的具体实现
// ⑤ 初始化应用上下文事件广播器
this.initApplicationEventMulticaster();
// ⑥ 初始化其他特殊的Bean,由具体子类实现
this.onRefresh();
// ⑦ 注册事件监听
this.registerListeners();
// ⑧ 调用后工厂处理器
this.finishBeanFactoryInitialization(beanFactory);
// ⑨ 完成刷新并发布容器刷新事件
Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了体系的搭建。
在⑤处初始化事件的广播器,用户可以在配置文件中为容器定义一个自定义的事件广播器,只要实现ApplicationEventMulticaster即可,Spring会通过反射机制将其注册成容器的事件广播器。如果没找到外部事件广播器,则Spring自动使用SimpleApplicationEventMulticaster作为事件广播器。
在⑦处,Spring通过反射机制,从BeanDefinitionRegister中找出所有实现ApplicationListener的Bean,将他们注册为容器的事件监听器,实际操作就是将其添加到事件广播器所提供的事件监听器注册表中。
在⑨处,容器启动完成,调用事件发布接口向容器中所有的监听器发布事件,在publishEvent()内部可以看到,Spring委托ApplicationEventMulticaster将事件通知给事件监听器。
参考:《精通Spring4.x企业级应用开发实战》