Spring ApplicationContext下的refresh()方法


public class BeanTest{
    @Test
    public void test(){
        ApplicationContext applicationContext  = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(applicationContext);
        Student student = (Student)applicationContext.getBean("student");
        student.play();
        System.out.println(student);
        //關閉容器
        ((AbstractApplicationContext)applicationContext).close();
    }
}

調用ApplicationContext,執行refresh() 

@Override
	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) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

  1、刷新容器前的預處理prepareRefresh

  
// Initialize any placeholder property sources in the context environment.
  //初始化一些屬性設置
  initPropertySources();

  // Validate that all properties marked as required are resolvable:
  // see ConfigurablePropertyResolver#setRequiredProperties
  //校驗屬性的合法性
  getEnvironment().validateRequiredProperties();
  // Allow for the collection of early ApplicationEvents,
  // to be published once the multicaster is available...
  //保存容器中的早期事件的容器 Set 集合
  this.earlyApplicationEvents = new LinkedHashSet<>();

  

  2、獲取 beanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

  //構造一個 beanFactory  

  this.beanFactory = new DefaultListableBeanFactory();

  //獲取 BeanFactory 返回的上一步構 GenericApplicationContext 類構造器創建的 beanFactory

  ConfigurableListableBeanFactory beanFactory = getBeanFactory();

  //返回 beanFactory 【ConfigurableListableBeanFactory 的實例實例對象】

  return beanFactory;

  3、beanFactory 的預准備工作  prepareBeanFactory(beanFactory);

  

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }

  4、beanFactory 准備完成的后置處理工作 postProcessBeanFactory(beanFactory);

  5、執行 beanFactoryPostProcessors 方法  invokeBeanFactoryPostProcessors(beanFactory);

    執行 invokeBeanFactoryPostProcessors 的方法 

    BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor

      先執行 BeanDefinitionRegistryPostProcessor 的方法
      再執行 BeanFactoryPostProcessors 的方法
   6、注冊 BeanPostProcessors 【 Bean 的后置處理器 】registerBeanPostProcessors(beanFactory);
    優先級接口PriorityOrdered 和 Ordered
   7、初始化 MessageSource 組件  initMessageSource();
   8、初始化事件派發器 initApplicationEventMulticaster();
   9、留給子容器(子類)onRefresh();
   10、給容器中將所有項目里面的ApplicationListener注冊進來  registerListeners();
   11、初始化所有剩下的單實例 Bean(沒有配置賴加載的 lazy!=true)  finishBeanFactoryInitialization(beanFactory);
    1>、初始化所有剩下的單實例bean
       beanFactory.preInstantiateSingletons();
    2>、將容器中所有的 bean 加入到 List中
       List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
    3>、遍歷該 List
       for (String beanName : beanNames) {
          ...
      }
    4>、獲取 bean 定義信息
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    5>、bean 不是抽象的、是單例的、非懶加載的
       if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
          ...
      }
    6>、是否為 FactoryBean ,是則調用 FactoryBean 的創建方法,否則執行 getBean() 方法
        if (isFactoryBean(beanName)) {
            ...     
      }
    7>、調用 getBean() 方法 -> 內部再調用 doGetBean() 方法
      (1)、嘗試從從緩存中獲取 bean
        Object sharedInstance = getSingleton(beanName);
 
        (2)、獲取 bean 定義信息
        RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 
      (3)、判斷是否有其他依賴,如果有其他依賴,注冊依賴的 bean 並調用 getBean() 方法創建
         String[] dependsOn = mbd.getDependsOn();
           if (dependsOn != null) {
       for (String dep : dependsOn) {       if (isDependent(beanName, dep)) {       throw new BeanCreationException(mbd.getResourceDescription(), beanName,     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");       }     registerDependentBean(dep, beanName);     getBean(dep);       }       }

      (4)、
進入單實例 bean 的創建流程  return createBean(beanName, mbd, args);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM