码迷,mamicode.com
首页 > 编程语言 > 详细

spring容器的启动过程(1)

时间:2015-11-08 15:27:20      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:

容器启动过程总体流程

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();
// 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);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
      }
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset ‘active‘ flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
      }
   }
}
第一个方法是prepareRefresh(),我们来看看这个方法具体都做什么了再总结下这个方法


prepareRefresh() {
.= System.();

(.) {
.= ;
   }

(.isInfoEnabled()) {
.info(+ );
   }
   // 初始化上下文环境,容器的一些信息这个时候加载了进来比如  文件路径信息
initPropertySources();
//查看标示为必填的属性信息是否都有了
getEnvironment().validateRequiredProperties();
}

prepareRefresh()只包含了两个方法,这两个方法加载了服务器的一些信息和判断必填项是否都完整。

第二个方法:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();


ConfigurableListableBeanFactory () {
 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
(.isDebugEnabled()) {
.debug(+ getDisplayName() + + beanFactory);
   }
beanFactory;
}

refreshBeanFactory()这个方法比较复杂,做了很多我们平时忽略的事情,让我们仔细查看一下。

protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
   //0-0   destroyBeans();
   //0-1   closeBeanFactory();
   }
try {//1
      DefaultListableBeanFactory beanFactory = createBeanFactory();//设置容器系列号,org.springframework.web.context.WebApplicationContext:
      beanFactory.setSerializationId(getId());
//2      customizeBeanFactory(beanFactory);
//3     loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
      }
   }
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
首先就是如果容器现在已经启动,而我们要新启动一个容器,那么首要的就是销毁以前的容器,具体过程如下
//0-0
 destroyBeans();
protected void destroyBeans() {
   getBeanFactory().destroySingletons();
}
public void destroySingletons() {
if (logger.isInfoEnabled()) {
logger.info("Destroying singletons in " + this);
   }
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
   }
   String[] disposableBeanNames;
synchronized (this.disposableBeans) {
      disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
   }
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
      destroySingleton(disposableBeanNames[i]);
   }
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
this.earlySingletonObjects.clear();
this.registeredSingletons.clear();
this.singletonsCurrentlyInDestruction = false;
   }
}
这一个步骤就是清空容器和容器中注册了的bean。
//0-1 
closeBeanFactory();
protected final void closeBeanFactory() {
synchronized (this.beanFactoryMonitor) {//对象序列号置空
this.beanFactory.setSerializationId(null);//对象释放
this.beanFactory = null;
   }
}
新建容器对象  DefaultListableBeanFactory beanFactory = createBeanFactory();新建一个DefaultListableBeanFactory.注意在这里面有一个方法getInternalParentBeanFactory(),这个方法获得并设置了父容器。当然在spring启动的过程中这个父容器是空的。
protected DefaultListableBeanFactory createBeanFactory() {
//
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
步骤2主要是判断了一下三件事情
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//bean是否允许覆盖
if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }//bean是否允许循环引用
if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }//把java注解和spring标准注解都放到了容器里面来了
   beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
}public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
this.autowireCandidateResolver = autowireCandidateResolver;
}

技术分享

步骤3要加载bean loadBeanDefinitions(beanFactory);我想这个过程应该是漫长而负责的。实现了该方法的类一共有三个1、XmlWebApplicationContext   2、AbstractXmlApplicationContext    3、AnnotationConfigWebApplicationContext.在项目启动的过程中XmlWebApplicationContext   真正的被执行。其余两个执行情况以后做研究。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 1 给指定工厂创建一个阅读器.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//.配置一个带有上下文资源环境的bean 定义阅读器,
beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//允许子类个性初始化阅读器,程序可以实现接口XmlWebApplicationContext实现该方法实现个性化定制。initBeanDefinitionReader(beanDefinitionReader);
//加载beanDefinations
  loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions(beanDefinitionReader);方法要加载bean的信息。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 1 给指定工厂创建一个阅读器.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//.配置一个带有上下文资源环境的bean 定义阅读器,
beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//允许子类个性初始化阅读器,程序可以实现接口XmlWebApplicationContext实现该方法实现个性化定制。initBeanDefinitionReader(beanDefinitionReader);
//加载beanDefinations
  loadBeanDefinitions(beanDefinitionReader);
}
loadBeanDefinitions(beanDefinitionReader);方法要加载bean的信息。

接下来的bean加载过程主要涉及到的就是配置文件解析。配置文件解析大体步骤1、根据命名空间将标签名称和解析类放置到map中2、读取配置文件的过程中遇到标签就将找到解析类去解析。这样解析类又会是非常重要的部分。接下来我会找到一个典型的解析类去阐述。未完待续。



spring容器的启动过程(1)

标签:

原文地址:http://my.oschina.net/zjItLife/blog/527640

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!