package org.springframework.beans.factory.xml;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.core.io.Resource;

public class XmlBeanFactory extends DefaultListableBeanFactory {

   private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
  
   public XmlBeanFactory(Resource resource) throws BeansException {
       this(resource, null);
   }

   public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
       super(parentBeanFactory);
       this.reader.loadBeanDefinitions(resource);
   }

}

멤버 변수 하나.. 생성자 두개.. 매우 Simple한 클래스입니다. 상속 구조는 다음과 같습니다.

1179800511.bmpAbstractBeanFactory는 지난 번에 살펴본적이 있기 때문에 이 위로는 생략하였습니다. 그리고 꽤 많은 인터페이스들이 오른쪽에 얽혀 있는데 클래스의 상속 구조에만 집중하기 위해 짤랐습니다.

AbstractBeanFactory와 XmlBeanFactory사이의 두 개의 클래스에서 많은 인터페이스들을 구현해주고 있는 모습을 확인 할 수 있습니다.(물론 AbstractBeanFactory도  BeanfFactory, ConfigurableBeanFactory, HierarchicalBeanFactory 인터페이스를 구현했습니다.)

XmlBeanFactory의 생성자에서 호출하는 reader.loadBeanDefinitions(resource); 메소드를 보겠습니다.
1198282148.bmp
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
       return loadBeanDefinitions(new EncodedResource(resource));
}

loadBeanDefinitions() 소스코드 보기
[#M_ more.. | less.. |
/**
    * Load bean definitions from the specified XML file.
    * @param encodedResource the resource descriptor for the XML file,
    * allowing to specify an encoding to use for parsing the file
    * @return the number of bean definitions found
    * @throws BeanDefinitionStoreException in case of loading or parsing errors
    */
   public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
       Assert.notNull(encodedResource, “EncodedResource must not be null”);
       if (logger.isInfoEnabled()) {
           logger.info(“Loading XML bean definitions from ” + encodedResource.getResource());
       }

       try {
           InputStream inputStream = encodedResource.getResource().getInputStream();
           try {
               InputSource inputSource = new InputSource(inputStream);
               if (encodedResource.getEncoding() != null) {
                   inputSource.setEncoding(encodedResource.getEncoding());
               }
               return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
           }
           finally {
               inputStream.close();
           }
       }
       catch (IOException ex) {
           throw new BeanDefinitionStoreException(
                   “IOException parsing XML document from ” + encodedResource.getResource(), ex);
       }
   }
_M#]
EncodedResource.getResource() 메소드가 Xml configuration Metadata를 읽어 들이는 핵심 부분인듯 합니다.

메소드 호출 순서를 보겠습니다.

  1. new XmlBeanFactory( ~, ~)
    1. reader.loadBeanDefinitions(resource)
      1. Assert.notNull(encodedResource, “Message”)
      2. logger.isInfoEnabled()
      3. logger.info(“Message” + encodedResource.getResource())
      4. encodedResource.getResource().getInputStream()
      5. encodedResource.getEncoding()
      6. 위 5번의 반환값이 null이 아니면
      7. inputSource.setEncoding(encodedResource.getEncoding())
      8. return doLoadBeanDefinitions(inputSource, encodedResource.getResource()
      9. inputStream.close()
      10. 위 4번 부터 9번 사이에 IOException이 발생하면
      11. throw new BeanDefinitionStoreException(“Message” + encodedResource.getResource(), ex)