标签:
容器启动过程总体流程
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的信息。
标签:
原文地址:http://my.oschina.net/zjItLife/blog/527640