Spring容器初始化过程
⼀、Spring 容器⾼层视图
Spring 启动时读取应⽤程序提供的Bean配置信息,并在Spring容器中⽣成⼀份相应的Bean配置注册表,然后根据这张注册表实例化Bean,装配号Bean之间的依赖关系,为上层应⽤提供准备就绪的运⾏环境。
⼆、内部⼯作机制
该图描述了Spring容器从加载配置⽂件到创建出⼀个完整Bean的作业流程:
1、ResourceLoader从存储介质中加载Spring配置信息,并使⽤Resource表⽰这个配置⽂件的资源;
2、BeanDefinitionReader读取Resource所指向的配置⽂件资源,然后解析配置⽂件。配置⽂件中每⼀个<bean>解析成⼀个BeanDefinition对象,并保存到BeanDefinitionRegistry中;
3、容器扫描BeanDefinitionRegistry中的BeanDefinition,使⽤Java的反射机制⾃动识别出Bean⼯⼚后处理后器(实现BeanFactoryPostProcessor接⼝)的Bean,然后调⽤这些Bean⼯⼚后处理器对BeanDefinitionRegistry中的BeanDefinition进⾏加⼯处理。主要完成以下两项⼯作:
1)对使⽤到占位符的<bean>元素标签进⾏解析,得到最终的配置值,这意味对⼀些半成品式的BeanDefinition对象进⾏加⼯处理并得到成品的BeanDefinition 对象;
2)对BeanDefinitionRegistry中的BeanDefinition进⾏扫描,通过Java反射机制出所有属性编辑器的Bean(实现java.beans.PropertyEditor接⼝的Bean),并⾃动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry);
4.Spring容器从BeanDefinitionRegistry中取出加⼯后的BeanDefinition,并调⽤InstantiationStrategy着⼿进⾏Bean实例化的⼯作;
5.在实例化Bean时,Spring容器使⽤BeanWrapper对Bean进⾏封装,BeanWrapper提供了很多以Java反射机制操作Bean的⽅法,它将结合该Bean的BeanDefinition以及容器中属性编辑器,完成Bean属性的设置⼯作;
6.利⽤容器中注册的Bean后处理器(实现BeanPostProcessor接⼝的Bean)对已经完成属性设置⼯作的Bean进⾏后续加⼯,直接装配出⼀个准备就绪的Bean。
Spring容器确实堪称⼀部设计精密的机器,其内部拥有众多的组件和装置。Spring的⾼明之处在于,它使⽤众多接⼝描绘出了所有装置的蓝图,构建好Spring
的⾻架,继⽽通过继承体系层层推演,不断丰富,最终让Spring成为有⾎有⾁的完整的框架。所以查看Spring框架的源码时,有两条清晰可见的脉络:
1)接⼝层描述了容器的重要组件及组件间的协作关系;
2)继承体系逐步实现组件的各项功能。
接⼝层清晰地勾勒出Spring框架的⾼层功能,框架脉络呼之欲出。有了接⼝层抽象的描述后,不但Spring⾃⼰可以提供具体的实现,任何第三⽅组织也可以提供不同实现,可以说Spring完善的接⼝层使框架的扩展性得到了很好的保证。纵向继承体系的逐步扩展,分步骤地实现框架的功能,这种实现⽅案保证了框架功能不会堆积在某些类的⾝上,造成过重的代码逻辑负载,框架的复杂度被完美地分解开了。
Spring组件按其所承担的⾓⾊可以划分为两类:
1)物料组件:Resource、BeanDefinition、PropertyEditor以及最终的Bean等,它们是加⼯流程中被加⼯、被消费的组件,就像流⽔线上被加⼯的物料;2)加⼯设备组件:ResourceLoader、BeanDefinitionReader、BeanFactoryPostProcessor、InstantiationStrategy以及BeanWrapper等组件像是流⽔线上不同环节的加⼯设备,对物料组件进⾏加⼯处理。
三、Spring容器-ApplicationContext的启动过程
ApplicationContext内部封装了⼀个BeanFactory对象,来实现对容器的操作,初始化完成之后,BeanFactory封装了bean的信息,⽽ApplicationContext 通过访问这个对象获取bean的对象信息(BeanDefinition/Bean对象,都是由BeanFactory实际创建并管理的),为了实现接⼝的统⼀,ApplicationContext也实现了⼀系列的BeanFactory接⼝(可以说ApplicationContext对BeanFactory对象实现⼀种代理)。ApplicationContext建⽴在BeanFactory的基础之上,对配置对象的管理最终还是交于⼀个DefaultListableBeanFactory来完成(装配地址/访问等),⽽ApplicationContext在应⽤这个DefaultListableBeanFactory对象的基础上,不仅实现了BeanFactory接⼝提供的功能⽅法,并且黏合了⼀些⾯向应⽤的功能,如资源/国际化⽀持/框架事件⽀持等,并且将⼀些原先需要⼿动设置到BeanFactory的属性通过配置⽂件中配置的形式代替(如⼯⼚后处理器BeanPostProcessor/InstantiationAwareBeanPostProcessor)
同样,因为对于BeanDefinition和bean对象的管理是由上下⽂持有的beanfactory对象完成的,⽤户不需要拥有这样的接⼝,因此,ApplicationContext的接⼝体系中并没有BeanDefinitionRegistry,SingletonBeanRegistry以及AutowireCapableBeanFactory接⼝(ApplicationContext可以访问⼀些接⼝⽅法在上述接⼝中也定义,但这些⽅法提供者为BeanFactory体系中的其他接⼝,BeanFactory接⼝体系中的接⼝之间有重复定义⽅法的)。
内部⼯作机制(Spring容器ApplicationContext的初始化)
(⼀)⾸先来看创建ApplicationContext ,以ClassPathXmlApplicationContext为例:
ApplicationContext = new ClassPathXmlApplicationContext(xmlPath);
源码如下:
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation});
}
public ClassPathXmlApplicationContext(String[] configLocations) throws BeansException {
this(configLocations, (ApplicationContext) null);
}
//。。。。。。省略⼏个重载的构造函数
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException { super(parent);
//IoC容器的初始化过程,其初始化过程的⼤致步骤由AbstractApplicationContext来定义
refresh();
}
关键之处在于refresh⽅法,此⽅法继承于ClassPathXmlApplicationContext的间接⽗类:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean {
Spring的AbstractApplicationContext是ApplicationContext抽象实现类,该抽象类的refresh()⽅法定义了Spring容器在加载配置⽂件后的各项处理过程,这些处理过程清晰刻画了Spring容器启动时所执⾏的各项操作(创建Spring容器如ClassPathXmlApplicationContext)。下⾯,我们来看⼀下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();--------(1)
// 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);-------------------------------------(2)
// Register bean processors that intercept bean creation
registerBeanPostProcessors(beanFactory);---------------------------------------------(3)
// Initialize message source for this context.
initMessageSource();-------------------------------------------------------------------------(4)
// Initialize event multicaster for this context.
initApplicationEventMulticaster();-----------------------------------------------------------(5)
// Initialize other special beans in specific context subclasses.
onRefresh();------------------------------------------------------------------------------------(6)
// Check for listener beans and register them.
registerListeners();----------------------------------------------------------------------------(7)
// Instantiate singletons this late to allow them to access the message source.
beanFactory.preInstantiateSingletons();--------------------------------------------------(8)
// Last step: publish corresponding event.
publishEvent(new ContextRefreshedEvent(this));---------------------------------------(9)
} catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
beanFactory.destroySingletons();
throw ex;
}
}
}
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
1.初始化BeanFactory:根据配置⽂件实例化BeanFactory,getBeanFactory()⽅法由具体⼦类实现。在这⼀步⾥,Spring将配置⽂件的信息解析成为⼀个个的BeanDefinition对象并装⼊到容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还未初始化;obtainFreshBeanFactory()会调⽤⾃⾝的refreshBeanFactory(),⽽refreshBeanFactory()⽅法由⼦类AbstractRefreshableApplicationContext实现,该⽅法返回了⼀个创建的DefaultListableBeanFactory 对象,这个对象就是由ApplicationContext管理的BeanFactory容器对象。
这⼀步的操作相当于,如果我们在⾃⼰的应⽤代码中不⽤ApplicationContext⽽直接⽤BeanFactory时创建BeanFactory对象的操作
核⼼代码如下:
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext { }
/** 该ApplicationContext管理的BeanFactory容器对象*/
private DefaultListableBeanFactory beanFactory;
protected final void refreshBeanFactory() throws BeansException {
// Shut down previous bean factory, if any.
ConfigurableListableBeanFactory oldBeanFactory = null;
synchronized (this.beanFactoryMonitor) {
oldBeanFactory = this.beanFactory;
}
if (oldBeanFactory != null) {
oldBeanFactory.destroySingletons();
synchronized (this.beanFactoryMonitor) {
this.beanFactory = null;
}
}
/
/ Initialize fresh bean factory.
try {
// 创建容器对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
// Customize the internal bean factory used by this context
customizeBeanFactory(beanFactory);
// 装载配置⽂件,并传⼊相关联的BeanFactory对象,作为BeanDefinition的容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException ex) {
throw new ApplicationContextException(
"I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
}
}
// 创建Spring默认的容器对象
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// 该⽅法为⼀个钩⼦⽅法,⼦类可以覆盖它对当前上下⽂管理的BeanFactory提供客户化操作,也可以忽略
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
}
// 装载配置⽂件的⽅法,需要⼦类实现
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws IOException, BeansException;
对于上⾯装载配置⽂件的⽅法,由其⼦类扩展实现:
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableApplicationContext {}
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
// 使⽤XMLBeanDefinitionReader来载⼊bean定义信息的XML⽂件,传⼊关联的BeanFactory
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 这⾥配置reader的环境,其中ResourceLoader是我们⽤来定位bean定义信息资源位置的
// 因为上下⽂本⾝实现了ResourceLoader接⼝,所以可以直接把上下⽂作为ResourceLoader传递⼊
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);
// 这⾥转到定义好的XmlBeanDefinitionReader中对载⼊bean信息进⾏处理
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
reader.loadBeanDefinitions(configLocations);涉及到XmlBeanDefinitionReader ⼯具类的使⽤(以后整理)
2.调⽤⼯⼚后处理器:根据反射机制从BeanDefinitionRegistry中出所有BeanFactoryPostProcessor类型的Bean,并调⽤其postProcessBeanFactory()接⼝⽅法;
经过第⼀步加载配置⽂件,已经把配置⽂件中定义的所有bean装载到BeanDefinitionRegistry这个Beanf
actory中,对于ApplicationContext应⽤来说这个BeanDefinitionRegistry类型的BeanFactory就是Spring默认的DefaultListableBeanFactory
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry
在这些被装载的bean中,若有类型为BeanFactoryPostProcessor的bean(配置⽂件中配置的),则将对应的BeanDefinition⽣成BeanFactoryPostProcessor 对象
容器扫描BeanDefinitionRegistry中的BeanDefinition,使⽤java反射⾃动识别出Bean⼯⼚后处理器(实现BeanFactoryPostProcessor接⼝)的bean,然后调⽤这些bean⼯⼚后处理器对BeanDefinitionRegistry中的BeanDefinition进⾏加⼯处理,可以完成以下两项⼯作(当然也可以有其他的操作,⽤户⾃⼰定义):
1 对使⽤到占位符的<bean>元素标签进⾏解析,得到最终的配置值,这意味着对⼀些半成品式的BeanDefinition对象进⾏加⼯处理并取得成品的BeanDefinition对象。
2 对BeanDefinitionRegistry中的BeanDefinition进⾏扫描,通过Java反射机制出所有属性编辑器的Bean(实现
java.beans.PropertyEditor接⼝的Bean),并⾃动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry),这个Spring提供了实现:CustomEditorConfigurer,它实现了BeanFactoryPostProcessor,⽤它来在此注册⾃定义属性编辑器;
AbstractApplicationContext中的代码如下:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// Invoke factory processors registered with the context instance.
for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
factoryProcessor.postProcessBeanFactory(beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// 通过ApplicatinContext管理的beanfactory获取已经注册的BeanFactoryPostProcessor类型的bean的名
字
String[] factoryProcessorNames =
// Separate between BeanFactoryPostProcessors that implement the Ordered
// interface and those that do not.
List orderedFactoryProcessors = new ArrayList();
List nonOrderedFactoryProcessorNames = new ArrayList();
for (int i = 0; i < factoryProcessorNames.length; i++) {
if (isTypeMatch(factoryProcessorNames[i], Ordered.class)) {
// 调⽤beanfactory的getBean取得所有的BeanFactoryPostProcessor对象
orderedFactoryProcessors.Bean(factoryProcessorNames[i]));
}
else {
nonOrderedFactoryProcessorNames.add(factoryProcessorNames[i]);
}
}
// First, invoke the BeanFactoryPostProcessors that implement Ordered.
Collections.sort(orderedFactoryProcessors, new OrderComparator());
for (Iterator it = orderedFactoryProcessors.iterator(); it.hasNext();) {
BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
spring启动流程面试回答// 执⾏BeanFactoryPostProcessor的⽅法,传⼊当前持有的beanfactory对象,以获取要操作的
// BeanDefinition
factoryProcessor.postProcessBeanFactory(beanFactory);
}
// Second, invoke all other BeanFactoryPostProcessors, one by one.
for (Iterator it = nonOrderedFactoryProcessorNames.iterator(); it.hasNext();) {
String factoryProcessorName = (String) it.next();
((BeanFactoryPostProcessor) getBean(factoryProcessorName)).
postProcessBeanFactory(beanFactory);
}
}
BeanFactoryPostProcessor接⼝代码如下,实际的操作由⽤户扩展并配置--扩展点
参考:
3.注册Bean后处理器:根据反射机制从BeanDefinitionRegistry中出所有BeanPostProcessor类型的Bean,并将它们注册到容器Bean后处理器的注册表中;
AbstractApplicatinContext中对应代码如下:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
String[] processorNames = BeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
int beanProcessorTargetCount = BeanPostProcessorCount() + 1 + processorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
List orderedProcessors = new ArrayList();
List nonOrderedProcessorNames = new ArrayList();
for (int i = 0; i < processorNames.length; i++) {
if (isTypeMatch(processorNames[i], Ordered.class)) {
orderedProcessors.add(getBean(processorNames[i]));
}
else {
nonOrderedProcessorNames.add(processorNames[i]);
}
}
// First, register the BeanPostProcessors that implement Ordered.
Collections.sort(orderedProcessors, new OrderComparator());
for (Iterator it = orderedProcessors.iterator(); it.hasNext();) {
/
/ 注册bean后处理器,该⽅法定义于ConfigurableBeanFactory接⼝
beanFactory.addBeanPostProcessor((BeanPostProcessor) it.next());
}
// Second, register all other BeanPostProcessors, one by one.
for (Iterator it = nonOrderedProcessorNames.iterator(); it.hasNext();) {
String processorName = (String) it.next();
beanFactory.addBeanPostProcessor((BeanPostProcessor) getBean(processorName));
}
}
整段代码类似于第三步的调⽤⼯⼚后处理器,区别之处在于,⼯⼚后处理器在获取后⽴即调⽤,⽽Bean后处理器在获取后注册到上下⽂持有的beanfactory 中,供以后操作调⽤(在⽤户获取bean的过程中,对已经完成属性设置⼯作的Bean进⾏后续加⼯,他加⼯的是bean,⽽⼯⼚后处理器加⼯的是BeanDefini
tion)
BeanPostProcessor 接⼝代码如下,实际的操作由⽤户扩展并配置--扩展点
参考:
4.初始化消息源:初始化容器的国际化信息资源;
源代码如下:
protected void initMessageSource() {
// 补充
}
5.初始化应⽤上下⽂事件⼴播器;(观察者模式中的具体主题⾓⾊,持有观察者⾓⾊的集合,称为注册表)
AbstractApplciationContext拥有⼀个applicationEventMulticaster 成员变量,applicationEventMulticaster 提供了容器的注册表,成其为事件⼴播器。在第七步中将会将事件监
听器装⼊其中
AbstractApplicationContext中的代码如下:
private ApplicationEventMulticaster applicationEventMulticaster;
protected void initApplicationEventMulticaster() {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论