Spring IoC容器初始化

时间:2021-09-17 19:39:53

Spring IoC容器初始化详解

环境说明

0.基于Spring3.2.7版本;
1.基于ApplicationContext context = new ClassPathXmlApplicationContext(path);容器;
2.本文的一些术语词汇以及类图关系可结合Spring IoC容器结构一节参考阅读。

详细执行过程:

1.new ClassPathXmlApplicationContext(path):

源码实现如下

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);//默认parent = null;
}

调用的下面这个构造函数:

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if(refresh) {
this.refresh();
}
}

(1).super(parent);//设置父上下文,继承自AbstractApplicationContext抽象类,默认为null;
(2).this.setConfigLocations(configLocations);//解析路径(占位符,通配符),设置存储配置文件路径;参数等于空则使用默认路径;
(3).可以看到,真正初始化工作是由refresh()方法执行的,它的实现在AbstractApplicationContext抽象类中,源码如下:

public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
//1.初始化准备工作
this.prepareRefresh();
//2.创建Bean工厂
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//3.配置上下文环境,比如类装载器、PostProcessor
this.prepareBeanFactory(beanFactory);

try {
//4.模板方法,为容器某些子类扩展功能所用(工厂后处理器)
//这里可以参考BeanFactoryPostProcessor接口的postProcessBeanFactory方法
this.postProcessBeanFactory(beanFactory);
//调用所有BeanFactoryPostProcessor注册为Bean
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册所有实现了BeanPostProcessor接口的Bean
this.registerBeanPostProcessors(beanFactory);
//初始化MessageSource,和国际化相关
this.initMessageSource();
//初始化容器事件传播器
this.initApplicationEventMulticaster();
//调用容器子类某些特殊Bean的初始化,模板方法
this.onRefresh();
//为事件传播器注册监听器
this.registerListeners();
//初始化所有剩余的bean(普通bean)
this.finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期事件处理器,并发布容器的生命周期事件
this.finishRefresh();
} catch (BeansException var5) {
//销毁已创建的bean
this.destroyBeans();
//取消refresh操作,如重置容器同步标识(prepareRefresh方法中)
this.cancelRefresh(var5);
throw var5;
}
}
}

  上面的方法,有的是在AbstractApplicationContext已经实现了,有的则是抽象方法(模板方法),供子类自己实现,实现多样化,多态化(模板设计模式)。

2.refresh()方法

1.prepareRefresh()
  容器初始化之前预处理工作,包括记录开始时间,设置容器同步标识等,源码如下:

protected void prepareRefresh() {
//记录容器开始初始化时间
this.startupDate = System.currentTimeMillis();
Object var1 = this.activeMonitor;
synchronized(this.activeMonitor) {
this.active = true;//设置容器同步标识
}

if(this.logger.isInfoEnabled()) {
this.logger.info("Refreshing " + this);
}
//空方法,由子类覆盖实现,初始化容器上下文中的property文件
this.initPropertySources();
this.getEnvironment().validateRequiredProperties();
}

执行后,在后台提示信息:

八月 12, 2016 5:19:48 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@27b4fe4d: startup date [Fri Aug 12 17:19:48 CST 2016]; root of context hierarchy

2.obtainFreshBeanFactory()
  关闭前面所有 bean 工厂,为新的上下文环境初始化一个新的 bean 工厂。这里需要子类来 协助完成资源位置定义 ,bean 载入和向 IoC 容器注册的过程。源码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//刷新容器
refreshBeanFactory();
//获得新的容器(在上面refreshBeanFactory方法中创建)
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}

  关键refreshBeanFactory方法,这是个模板方法,真正实现在子类AbstractRefreshApplicationContext中,其实现如下:

protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {//判断是否已有BeanFactory容器,有,则销毁这上面的bean,并关闭容器
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();//创建新的容器
beanFactory.setSerializationId(getId());
//定制容器,设置启动参数(bean可覆盖、循环引用),开启注解自动装配
customizeBeanFactory(beanFactory);
//将所有BeanDefinition载入beanFactory中,模板方法,具体由子类实现
loadBeanDefinitions(beanFactory);
//beanFactory同步
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

  loadBeanDefinitions()这个方法由AbstractXmlApplicationContext提供了一个实现,其实现具体又由AbstractBeanDefinitionReader提供,其主要工作是:将文件变为Resource,再将Resource转化为BeanDefinition(通过XML DOM方式解析),随后存储到beanFactory的BeanDefinitionMap中(这里的bean都是普通bean)。详细步骤可参考:Spring IOC源码详解之容器初始化(小鱼)
  执行该步骤后,控制台打印相关日志信息:

八月 12, 2016 5:19:48 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from file [/Users/fuchaochao/joy/spring-test2/target/classes/config/spring/local/appcontext-service.xml]

3.prepareBeanFactory()
  设置bean的类加载器,扫描并添加ApplicationContextAwareProcessor(注入实现ApplicationContextAware/ResourceLoaderAware/ApplicationEventPublisherAware/MessageSourceAware接口的bean),为bean添加相应环境(以后可能要读取各种环境的配置属性)。关于Spring的环境(Environment)可以参考:Spring3.1新属性管理API:PropertySource、Environment、Profile(zhang)

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置bean类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//设置Spring语言表达式(SpEL)解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

//扫描ApplicationContextAware bean
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

//注册类加载期类型切面织入(AOP)LoadTimeWeaver
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

//为各种加载进入beanFactory的bean配置默认环境
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

4.postProcessBeanFactory()
  这里注意和下一步区分,这里的postProcessBeanFactory是模板方法,是提供给子类实现的,子类可以有自己的特殊对BeanDefinition后处理方法,即子类可以在这对前面生成的BeanDefinition,即bean的元数据再处理。比如修改某个bean的id/name属性、scope属性、lazy-init属性(只要是配置文件上面可配置属性均可修改)等。
5.invokeBeanFactoryPostProcessors()
  调用所有BeanFactoryPostProcessor,它同样是一个接口,实现了此接口的类需重写postProcessBeanFactory()这个方法,是的,和第4步作用是一样的,不过这里可以看出,是作为一个接口,提供给用户(开发者)对BeanDefinition做再处理。
6.registerBeanPostProcessors()
  注册实现了BeanPostProcessor接口的bean,BeanPostProcessor这个接口的作用是让开发者通过重写其两个方法,从而对bean初始化(所有普通bean)前后做相关操作。源码如下:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//获得所有实现了BeanPostProcessor的bean的name
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
//添加并实例化一个BeanPostProcessor,这个是用来记录一些信息的
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

// 按是否实现了PriorityOrdered,Ordered以及其他区分这些BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}

// 首先注册实现了PriorityOrdered的,这些的bean的两个方法也会优先被执行
OrderComparator.sort(priorityOrderedPostProcessors);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

// 其次是实现了Ordered接口的
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
OrderComparator.sort(orderedPostProcessors);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);

// 再之后,是其他的
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

// 最后,是所有内部的BeanPostProcessor
OrderComparator.sort(internalPostProcessors);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector());
}

7.initMessageSource()
  初始化消息处理源,如果没有定义,则使用默认的。

protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();//获得当前容器
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {//判断是否有实现了MessageSource的bean,有则获取并注册
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// 若该bean实现HierarchicalMessageSource接口,并且本容器的父容器不为空
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// 设置的MessageSource的父级为空
// 设置默认的父级(父MessageSource),如果父容器存在MessageResource则以此为默认,否则以父容器为默认(父容器本身就是一个MessageResource)
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
//使用一个空的MessageResource处理消息
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}

8.initApplicationEventMulticaster()
  初始化容器事件传播器(或广播器),其逻辑同第7步,即先检查是否有自定义的ApplicationEventMulticaster,有则从beanFactory中的BeanDefinitionMap中获取并注册,否则创建一个默认的传播器,即SimpleApplicationEventMulticaster。
9.onRefresh()
  模板方法,供子类实现其特殊的容器初始化工作。
10.registerListeners()
  注册那些声明为bean的监听器(注册到前面的事件传播器上),即实现了ApplicationListener接口的,这里不会涉及到其他监听器。关于Spring的事件可以参考:Spring事件体系(caihaijiang)
11.finishBeanFactoryInitialization()
  实例化剩余的所有单例bean(单例bean,且lazy-init=false,在容器初始化时就实例化,以后可直接取用)。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为容器初始化类型转化器
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}

String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}

//停止使用临时的类加载器(加载bean时设置)
beanFactory.setTempClassLoader(null);

// 冰冻配置,之后无法更改BeanDefinition元数据
beanFactory.freezeConfiguration();

// 初始化所有单例非延迟bean(singleton&lazy-init==false)
beanFactory.preInstantiateSingletons();
}

执行这步骤后,控制台输出:

八月 15, 2016 4:54:54 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7e8a8fc4: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,helloWorld,com.fcc.spring.test.InitBeanPostProcessor#0,com.fcc.spring.test.InstanceBeanPostProcessor#0,com.fcc.spring.test.BeanFactoryPostProcessorTest#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy

12.finishRefresh()
  初始化最后步骤,将容器初始化这个工作作为一个事件发布出去,并通过事件传播器传播出去。
13.destroyBeans()
  容器初始化出错,将本容器所管理的bean摧毁,但是容器并没有摧毁,还是激活状态。
14.cancelRefresh()
  将第一步的容器同步标识active设置为false。

总结

本节总结

Spring容器,指的就是IoC容器,其初始化步骤为:
1.创建容器对象,设置父容器、配置文件;
2.容器预处理,主要是设置容器同步标识(标识当前容器是否激活);
3.关闭旧容器,读取配置文件,将其普通bean的元数据BeanDefinition注册到beanFactory中;(bean这个时候并没有实例化)
4.针对子类的或用户自定义的,执行postBeanPostProcessor方法,对BeanDefinition做后处理工作;
5.注册BeanPostProcessor;
6.初始化MessageResource;
7.初始化事件传播器;
8.子类自有容器初始化工作;
9.注册监听器bean;
10.实例化单例非延迟bean;
11.发布容器生命周期事件。

最后

  很多东西自己也没搞得很懂,这里只是个大概的流程,大家边看着边查边验证吧,以后自己慢慢熟悉再慢慢更新。