spirng源码阅读日记2--spring ioc

以ClassPathXmlApplicationContext的构造函数为入口点。(ClassPathXmlApplicationContext继承图见上一日记)
public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

重点就在于refresh()方法,该接口是ConfigurableApplicationContext中定义的,AbstractApplicationContext实现了该方法,如下:

public void refresh() throws BeansException, IllegalStateException {
   synchronized ( this. startupShutdownMonitor) {
      // Prepare this context for refreshing.
      //初始化一些参数,校验一些必须的属性是否配置
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      //创建一个新的beanFactory,重新加载bean的定义
      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();
      }

这只是一个模版方法,定义基本的操作骨架,涉及的一些抽象方法必须在延迟到子类中实现。
Refresh()方法的功能主要是重新生成一个beanFactory(DefaultListableBeanFactory类型),然后执行加载bean定义,生成对应的BeanDefinition对象保存在beanFactory中的map属性中。这一功能的主要实现主要通过 obtainFreshBeanFactory() 方法,继续跟进:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if ( logger.isDebugEnabled()) {
      logger.debug( "Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

refreshBeanFactory方法是一个抽象方法,具体的代码逻辑我们可以根据之前的关于applicationContext的继承线中查找离ClassPathXmlApplicationContext最近的实现了该方法的类(这里是AbstractRefreshableApplicationContext),具体实现代码如下:
@Override
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      //一个模版方法,默认是销毁所有在beanFactory中的缓存的单例对象(CurrentHashMap保存kv)
      destroyBeans();
      //将beanFactory变量指向null
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      //默认实现为设置beanFactory的setAllowBeanDefinitionOverriding和setAllowCircularReferences
      customizeBeanFactory(beanFactory);
      //根据beanFactory得到资源,读取资源并解析,封装为BeanDefinition对象,通过beanFactory注册该bean定义对象到map容器中
      loadBeanDefinitions(beanFactory);
      synchronized ( this. beanFactoryMonitor) {
         this. beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException( "I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

这个方法中的一些操作的具体作用都在注释中标明了,最关键的代码就是loadBeanDefinitions()方法,该方法会加载配置文件中的bean定义,详细代码如下:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment( this.getEnvironment());
   beanDefinitionReader.setResourceLoader( this);
   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);
   loadBeanDefinitions(beanDefinitionReader);
}

其中的XmlBeanDefinitionReader是xml文件格式配置的bean定义读取类,真正的bean定义的加载逻辑就是委托它来实现的。在这里我们将beanFactory作为构造参数传递给XmlBeanDefinitionReader,XmlBeanDefinitionReader内部会将该beanFactory作为一个bean定义的注册器BeanDefinitionRegistry。继续跟loadBeanDefinitions(),代码如下:
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

主要判断下当前上下文中是否有资源,如果有就直接加载,没有的话,会根据location通过 ResourceLoader获取资源,然后再执行这个方法。

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   //EncodedResource(resource):包装resource,获取字符输入流的时候根据编码和字符集将原始字节流转换。
   return loadBeanDefinitions( new EncodedResource(resource));
}

我们直接跳过一些代码,一直跟进和bean定义加载有关的方法,最后会到这么一个方法中:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      //使用jdk1.8 rt.jar中的使用sax解析xml文件的方式,得到Document对象
      Document doc = doLoadDocument(inputSource, resource);
      return registerBeanDefinitions(doc, resource);
   }
   catch (BeanDefinitionStoreException ex) {
      throw ex;
   }
   //后续都是一些catch操作,直接省略
   ……………..
}

根据输入源inputSource获取对应的输入流,再解析为代表整个xml配置文件的document对象,最后执行beanDefinitions的注册操作。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   //创建一个DefaultBeanDefinitionDocumentReader类型的实例
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   int countBefore = getRegistry().getBeanDefinitionCount();
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

BeanDefinitionDocumentReader为用于读取解析包含spring bean定义的document的spi。这里的实际类型为DefaultBeanDefinitionDocumentReader。
createReaderContext(resource)方法会生成一个xml读取上下文对象,并且会将this指向XmlBeanDefinitionReader对象赋给上下文内部的reader属性。
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   //readerContext中的XmlBeanDefinitionReader类型的reader属性中的registry为传递进去的beanFactory
   // (该beanFactory实现了beanDefineRegister接口)
   this. readerContext = readerContext;
   logger.debug( "Loading bean definitions");
   Element root = doc.getDocumentElement();
   doRegisterBeanDefinitions(root);
}

注意,这里该方法将readerContext对象赋给了同名的内部属性,后面注册beanDefinitions时,使用的就是readerContext中的XmlBeanDefinitionReader对象的registry(其实就是DefaultListableBeanFactory类型的对象)属性,调用相关注册接口完成注册操作。
继续跳过一些非功能性代码,继续跟进:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   //1.该标签为空,2.该标签的 xmlns = http://www.springframework.org/schema/beans,说明为 根标签
   if (delegate.isDefaultNamespace(root)) {
      NodeList nl = root.getChildNodes();
      for ( int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         if (node instanceof Element) {
            Element ele = (Element) node;
            if (delegate.isDefaultNamespace(ele)) {
               //解析spring中的默认标签
               parseDefaultElement(ele, delegate);
            }
            else {
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      delegate.parseCustomElement(root);
   }
}

这里会获取root节点()下的所有子节点,下面我跟进parseDefaultElement方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      importBeanDefinitionResource(ele);
   }
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      processAliasRegistration(ele);
   }
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      processBeanDefinition(ele, delegate);
   }
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // recurse
      doRegisterBeanDefinitions(ele);
   }
}

这里它会判断当前节点名为import,alias,bean,还是beans,来进行进一步的操作,这里我们以bean为例子。
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // Register the final decorated instance.
         BeanDefinitionReaderUtils. registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error( "Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      getReaderContext().fireComponentRegistered( new BeanComponentDefinition(bdHolder));
   }
}

这里第一步生成了BeanDefinitionHolder对象,该对象其实就是BeanDefinition持有对象,内部还有beanName,aliases属性,跟进
delegate.parseBeanDefinitionElement(ele)方法,这次跳过中间的一些方法,直接到最终解析element节点封装为BeanDefinition对象的方法
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
      @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

   if (ele.hasAttribute( SINGLETON_ATTRIBUTE)) {
      error( "Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
   }
   else if (ele.hasAttribute( SCOPE_ATTRIBUTE)) {
      bd.setScope(ele.getAttribute( SCOPE_ATTRIBUTE));
   }
   else if (containingBean != null) {
      // Take default from containing bean in case of an inner bean definition.
      bd.setScope(containingBean.getScope());
   }

   if (ele.hasAttribute( ABSTRACT_ATTRIBUTE)) {
      bd.setAbstract( TRUE_VALUE.equals(ele.getAttribute( ABSTRACT_ATTRIBUTE)));
   }

   String lazyInit = ele.getAttribute( LAZY_INIT_ATTRIBUTE);
   if ( DEFAULT_VALUE.equals(lazyInit)) {
      lazyInit = this. defaults.getLazyInit();
   }
   bd.setLazyInit( TRUE_VALUE.equals(lazyInit));

   String autowire = ele.getAttribute( AUTOWIRE_ATTRIBUTE);
   bd.setAutowireMode(getAutowireMode(autowire));

   if (ele.hasAttribute( DEPENDS_ON_ATTRIBUTE)) {
      String dependsOn = ele.getAttribute( DEPENDS_ON_ATTRIBUTE);
      bd.setDependsOn(StringUtils. tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
   }

   String autowireCandidate = ele.getAttribute( AUTOWIRE_CANDIDATE_ATTRIBUTE);
   if ( "".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
      String candidatePattern = this. defaults.getAutowireCandidates();
      if (candidatePattern != null) {
         String[] patterns = StringUtils. commaDelimitedListToStringArray(candidatePattern);
         bd.setAutowireCandidate(PatternMatchUtils. simpleMatch(patterns, beanName));
      }
   }
   else {
      bd.setAutowireCandidate( TRUE_VALUE.equals(autowireCandidate));
   }

   if (ele.hasAttribute( PRIMARY_ATTRIBUTE)) {
      bd.setPrimary( TRUE_VALUE.equals(ele.getAttribute( PRIMARY_ATTRIBUTE)));
   }

   if (ele.hasAttribute( INIT_METHOD_ATTRIBUTE)) {
      String initMethodName = ele.getAttribute( INIT_METHOD_ATTRIBUTE);
      bd.setInitMethodName(initMethodName);
   }
   else if ( this. defaults.getInitMethod() != null) {
      bd.setInitMethodName( this. defaults.getInitMethod());
      bd.setEnforceInitMethod( false);
   }

   if (ele.hasAttribute( DESTROY_METHOD_ATTRIBUTE)) {
      String destroyMethodName = ele.getAttribute( DESTROY_METHOD_ATTRIBUTE);
      bd.setDestroyMethodName(destroyMethodName);
   }
   else if ( this. defaults.getDestroyMethod() != null) {
      bd.setDestroyMethodName( this. defaults.getDestroyMethod());
      bd.setEnforceDestroyMethod( false);
   }

   if (ele.hasAttribute( FACTORY_METHOD_ATTRIBUTE)) {
      bd.setFactoryMethodName(ele.getAttribute( FACTORY_METHOD_ATTRIBUTE));
   }
   if (ele.hasAttribute( FACTORY_BEAN_ATTRIBUTE)) {
      bd.setFactoryBeanName(ele.getAttribute( FACTORY_BEAN_ATTRIBUTE));
   }

   return bd;

经过上面的解析,成功构造出一个BeanDefinitionHolder对象,该对象中的属性详细记录了bean创建时的一些细节,比如是否支持懒加载,是否为单例,初始化方法和销毁方法等等...
bean定义解析完成后,就是注册方法
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // Register the final decorated instance.
         BeanDefinitionReaderUtils. registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error( "Failed to register bean definition with name '" +
               bdHolder.getBeanName() + "'", ele, ex);
      }
      // Send registration event.
      getReaderContext().fireComponentRegistered( new BeanComponentDefinition(bdHolder));
   }
}


继续跟进注册方法:
public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   String beanName = definitionHolder.getBeanName();
   //注册bean定义,这里的registry对象的实际类型为实现了BeanDefinitionRegistry接口的DefaultListableBeanFactory对象
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

这里首先取出beanName, 然后获得registry对象(也就是DefaultListableBeanFactory对象),有了beanName, beanDefinition,beanFactory就可以将该xml配置文件中标签定义的beanName和创建细节维护到一个DefaultListableBeanFactory内部的一个beanDefinitionMap对象中。

到现在为止,bean定义的加载逻辑就全部理完了。

加载bean定义完成后,spring就会执行非懒加载的单例对象的初始化。这点主要在finishBeanFactoryInitialization(beanFactory)方法中实现。
首先spring会获取beanFactory中的beanDefinitionMap, 然后遍历判断是否为非抽象非懒加载单例模式,然后执行创建逻辑。如果该单例对象不是一个factoryBean,那么会直接调用getBean(beanName)方法,判断beanFactory中的单例缓存池(DefaultSingletonBeanRegistry中的 singletonObjects)中是否含有该对象,有,返回该对象,没有,根据beanDefinition执行创建逻辑,并将创建后的对象添加进singletonObjects中 然后返回。

你可能感兴趣的:(spring源码)