Spring ApplicationContext源码分析

代码的入口:

@Test
public void testFileXmlApplicationContext() {

    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring.xml");

    Person person = applicationContext.getBean("person", Person.class);
    person.info();
}

其中 ClassPathXmlApplicationContext 的类的继承层次图:

 

Spring加载的时序图:

这个过程中关键的方法是  AbstractApplicationContext,这个方法中挂念的方法是  refresh()方法。这个方法中有13个步骤。refresh是一个典型的模板模式,其中对应ApplicationContext的加载是在AbstractApplicationContext中实现的。其中依赖的一个步骤是交给不同的子类来实现的。分别对这个13个步骤进行描述:

1.prepareRefresh();// Prepare this context for refreshing.准备一下,这个Context将会进行刷新。

//为刷新准备此上下文,设置其启动日期和
		//活动标志以及执行属性源的初始化。
	protected void prepareRefresh() {
  	 this.startupDate = System.currentTimeMillis();
  	 this.closed.set(false);
  	 this.active.set(true);

  	 if (logger.isInfoEnabled()) {
     	 logger.info("Refreshing " + this);
   	}

   	// 初始化所有的上下文环境中的占位符属性元,点进去一看啥都没有。
   	initPropertySources();

  	 // 验证所有的required属性被正确的设置。//这个到底干了啥呀?这个requred属性到底是那些呢?这个没有用过。
  	 getEnvironment().validateRequiredProperties();

   	// 先将ApplicationEvent的队列给建立起来。
  	 this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
	}

2、ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 这个是一个将BeanFactoy的加载的过程,这个方法执行完毕后,所有的定义的BeanDefinition和其他的对象都会被加载到当前BeanFactory中来

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   		refreshBeanFactory();//刷新一下BeanFactory,这个方法是一个抽象方法,具体的实现是在其子类(AbstractRefreshableApplicationContext)中实现的。
   		ConfigurableListableBeanFactory beanFactory = getBeanFactory();//获取到对应的BeanFactory,然后返回。
   		if (logger.isDebugEnabled()) {
    		  logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
  		 }
   		return beanFactory;
	}

可以看一下  (AbstractRefreshableApplicationContext)中的refreshBeanFactory()方法。

2.1、refreshBeanFactory()

protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

第一步:判断当前是否有BeanFactory,如果有的话,将BeanFactory ,缓存等相关信息清空。

第二步:创建一个DefaultListableBeanFactory,其中BeanFactory就创建在AbstractRefreshableApplicationContext中进行维护。

第三步:定制当前的BeanFactory,这个主要是能否进行重写和循环引用。

第四步:加载所有的Beans到BeanFactory中来。loadBeanDefinitions(DefaultListableBeanFactory beanFactory)。这个方法是一个抽象方法。这个方法没有实现。交给了子类去实现。

这个方法没有实现的原因:当前的类是AbstractRefreshableApplicationContext中,当前的对象并不知道Resource是哪一个,没有办法确认应该将加载的任务委托给哪一个BeanDefinitionReader。对于  AbstractRefreshableApplicationContext 来讲,就是讲  refreshBeanFactory就是将BeanFactory创建好,并加载好。当时如何加载的还不能确定,这个需要交给底层的方法去实现。

2.2、loadBeanDefinitions(DefaultListableBeanFactory beanFactory)

这个时候看下loadBeanDefinitions(beanFactory) 是如何实现的。

这个方法是在AbstractXmlApplicationContext中实现的。,从类名中可以看出这个方法是XML的,主要是处理以Xml的方式定义的BeanDefinition信息。AbstractXmlApplicationContext,这个类的两个子类是ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext 。在子类中定义了Resource的类型。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//创建一个XmlBeanDefinitionReader,这个类的选择和 AbstractXmlApplicationContext 对应。

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());//设置当前的environment的对象。
   beanDefinitionReader.setResourceLoader(this);//设置对应的ResourceLoader。 ApplicationContext是ResourceLoader的子类。
   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);//设置 reader的属性validateing,设置是否使用xml验证。缺省是true。
   loadBeanDefinitions(beanDefinitionReader);//加载对应的BeanDefinitionReader对象。
}

 

2.3、loadBeanDefinitions(XmlBeanDefinitionReader reader)

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();//首先是getResources().
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();//这里是所有定义的文件的地址。
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

其中:Resource[] getConfigResources() 这个方法是获取所有的Resource的方法。这个方法教给了子类ClassPathXmlApplicationContext或者是FilePathXmlApplicationContext实现的。

String[] getConfigLocations()  是AbstractRefreshableConfigApplicationContext,中定义的方法,这个其中在ClassPathXmlApplicationContext中的方法主要是通过这个 void setConfigLocations(String... locations)将配置文件地址的信息写到当前的对象中的。AbstractRefreshableConfigApplicationContext 类主要定义的就是当前FilePathXmlApplicationContext和ClassPathXmlApplicationContext中定义的locations地址。这个类一般是 ClassPathXmlApplicationContext 和FileSystemXmlApplicationContext 一起配套使用的。

 

3、prepareBeanFactory(beanFactory);//对Bean Factory中的一些其他的信息信息配置。

        在上一步中主要是建立了一个DefaultListableBeanFactory,然后所有定义在xml文件中的  BeanDefinition的信息加载到当前的BeanDefinition中来。这个过程中BeanDefinition并没有被实例化,还是一些定义的信息。这里先对BeanFactoy中配置一些基础的参数。具体代码如下。将ClassLoader,一些其他的基础的类型加载到对应的系统中来。

4、postProcessBeanFactory(beanFactory)

在标准的 初始化之后,需要修改ApplicationContext中的内部BeanFactory的内容。所有的Bean  Definition都被load,但是还没实例化。这能够实现将特定的  BeanPostProcessor注册到特定的  ApplicationContext的实现中去。这个方法是为了 AbstractApplicationContext 的子类来实现的。

5.invokeBeanFactoryPostProcessors(beanFactory);//触发后置处理器。

  BeanFactoryPostProcessor这个类是BeanFactory 的PostProcessor的实现。BeanFactoryPostProcessor主要实现的可以对BeanDefinition的定义(配置数据,并不是实例化对象)进行处理。IOC容器允许BeanFactoryPostProcessor在实例化BeanDefinition之前对当前的配置数据进行修改。用户可以扩展多个BeanFactoryPostProcessor来实现对于BeanDefinition定义的数据进行修改。其中BeanFactoryPostProcessor主要是定义在了AbstractApplicationContext对象中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

 

第一步是public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)//将BeanFactoryPostProcessor 作用在当前的BeanFactory中去。

第二步是 其中如果当前的BeanFactoy中包含了  loadTimeWeaver bean的时候,这个时候需要配置一个LoadTimeWeaverAwareProcessor,同时添加一个 新的ClassLoader来实现加载是的Weaveer。

6、registerBeanPostProcessors(beanFactory);//注册BeanPostProcessor到当前的BeanFactory中去。

简单介绍下BeanPostProcessor;如果我们想对实例化后的BeanDefinition对象进行处理,可以通过实现一个 BeanPostProcessor的子类。BeanPostProcessor 是容器级别的,只有定义在一个容器中BeanPostProcessor才会作用。其中在ApplicationContext和BeanFactoy中是ApplicationContext会在refresh中将当前所有的BeanPostProcessor注册到BeanFactory中去。但是BeanFacoty需要自己手动的调用BeanFactoy中的addBeanPostProcessor来实现。

主要是调用  PostProcessorRegistrationDelegate 方法中对应的 registerBeanPostProcessors,方法来将所有的BeanProcessor注册到对应的BeanFactory中去的。

7.protected void initMessageSource()//初始化MesageSource

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {//如果BeanFactoy中已经定义了MessageSource的实例
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);//就使用这个MessageSource。
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {//然后看下如果这个Mesage是支持继承的,就把parenetBeanFactory(如果有)中的MessageSource放进去。
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isDebugEnabled()) {
         logger.debug("Using MessageSource [" + this.messageSource + "]");
      }
   }
   else {//如果没有定义,那么就使用一个默认的   DelegatingMessageSource 。
      // Use empty MessageSource to be able to accept getMessage calls.
      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 + "]");
      }
   }
}

简而言之:MessageSource主要是首先看用户是否定义了,如果定义了再看下是否是支持继承的MessageSource,如果支持就把父BeanFacoty中的MessageSource设置进去。如果用户没有定义就设置一个默认的DelegatingMessageSource

8.initApplicationEventMulticaster();//初始化事件广播

主要实现是看用户是否自定了事件广播,如果定义了就设置为用户制定的事件广播,否知设置一个 默认的时间广播。

 

9.onRefresh()//这个方法是一个模板方法,是交给子类来扩展的。

 

10.registerListeners();//注册所有的Listener。

protected void registerListeners() {
   // Register statically specified listeners first.
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // Do not initialize FactoryBeans here: We need to leave all regular beans
   // uninitialized to let post-processors apply to them!
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // Publish early application events now that we finally have a multicaster...
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

这个过程首先是将  当前AbstractApplicationContext中有的所有的ApplicationListener注册广播器中的Listener中去。

然后将所有的用户定义的ApplicationListener注册到广播中去。

然后将所有的  this.earlyApplicationEvents 中的定义的事件进行广播。

11.finishBeanFactoryInitialization(beanFactory);//实例化所有的非延迟加载的单例Bean对象。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // Initialize conversion service for this context.
   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));
   }

   // Register a default embedded value resolver if no bean post-processor
   // (such as a PropertyPlaceholderConfigurer bean) registered any before:
   // at this point, primarily for resolution in annotation attribute values.
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
         @Override
         public String resolveStringValue(String strVal) {
            return getEnvironment().resolvePlaceholders(strVal);
         }
      });
   }

   // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   // Stop using the temporary ClassLoader for type matching.
   beanFactory.setTempClassLoader(null);

   // Allow for caching all bean definition metadata, not expecting further changes.
   beanFactory.freezeConfiguration();

   // Instantiate all remaining (non-lazy-init) singletons.
   beanFactory.preInstantiateSingletons();
}

首先为这个ApplicationContext设置 CONVERSIONSERVICE的BeanName。

然后对于 LoadTimeWeaverAware 的Bean进行加载。

将零时的ClassLoader设置为null。

清空缓存 frozenBeanDefinitionNames

初始化剩余的所有的 非懒加载的  单例Singleton的单实例。

12:finishRefresh();//  发布相关的事件

protected void finishRefresh() {
   // 为这个ApplicationContext设置LifecycleProcessor。
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

第一步是如果当前容器中没有 定义LifeCleProcessor那么就使用一个默认的 DefaultLifecycleProcessor。关于LifeCycleProcessor的相关知识,会后面单独来将,这里按下不表。

第二步获取到所有的LifecycleProcessor对象,然后使用这个调用 onRefesh()对象来实现的。

第三步:发布最终实现的事件

第四步:不太了解,和LiveBeansView 相关。

13. resetCommonCaches()//将常用的cache都青空。

 

总结:

对于ApplicationContext的继承体系。

ClassPathXmlApplicationContext;类主要是确定当前的定义的Resource的位置。同时调用父类的方法来完成依赖注入的过程。

  1.   protected Resource[] getConfigResources()//继承AbstractXmlApplicationContext;这个方法会被父类调用。
  2.  public void setConfigLocations(String... locations)//调用了父类 AbstractRefreshableConfigApplicationContext的方法,这个方法是设置Resource对应的locations。

AbstractXmlApplicationContext:当前类主要是对于类的BeanDefinition的方法进行加载。

  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)//这个方法是继承自AbstractRefreshableApplicationContext:这个方法的主要是从底层方法指定的Resoure信息,和父类中指定的DefaultListableBeanFactory,使用一个合适的BeanDefinitionReader来将BeanDefinition的继承信息填到对应的BeanFactoy中。当前类是AbstractXmlApplicationContext,所以用XmlBeanDefinitionReader来读取。其实这个方法是一个来料加工的过程。
  2. protected String[] getConfigLocations()//在loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 的方法中调用了AbstractRefreshableConfigApplicationContext;中的方法,其中对应的locations地址是在ClassPathXmlApplicationContext中设置的。

AbstractRefreshableConfigApplicationContext:这个方法主要维护locations的属性。以及其他的一些配置信息。

AbstractRefreshableApplicationContext :这个方法中主要是维护了BeanFactory。其中DefaultListableBeanFactory就是在这个类中创建的。

  1. protected final void refreshBeanFactory();//当前方法继承自AbstractApplicationContext;主要工作是初始化 了DefaultListableBeanFactory。
  2. protected void cancelRefresh(BeansException ex);//  关闭refres的过程,同时将异常形象传递过来。

 

AbstractApplicationContext:这个方法是ApplicationContext体系的核心,其中refresh()方法是核心中的关键,实现了 IOC的依赖注入的关键步骤。同时依赖子类实现BeanDefinion的信息加载的过程。然后根据BeanFactoy ,对BeanFactoyPostProcessor,MessageSource,Listener,BeanPostProcessor等功能的实现,以及对于所有的非延迟加载的BeanDefinition进行实例化。

转载于:https://my.oschina.net/u/3388174/blog/880096

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值