XmlBeanFactory源码分析

来源:互联网 发布:淘宝南山射钉枪配件 编辑:程序博客网 时间:2024/05/20 22:03
public class XmlBeanFactory extends DefaultListableBeanFactory {private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);/** * Create a new XmlBeanFactory with the given resource, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @throws BeansException in case of loading or parsing errors */public XmlBeanFactory(Resource resource) throws BeansException {this(resource, null);}/** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * @param resource XML resource to load bean definitions from * @param parentBeanFactory parent bean factory * @throws BeansException in case of loading or parsing errors */public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {super(parentBeanFactory);this.reader.loadBeanDefinitions(resource);}}

这个类的代码很简单,一个成员对象加两个构造函数,从这里我们可以看出,最重要的地方在于最后一个构造函数:

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


 

第一句就是将父亲工厂交给父类的构造函数,实际上最后也就是把父工厂保存到类的parentBeanFactory成员对象中,这个对象是在AbstractBeanFactory抽象类中定义的,而这个父工厂也会一直传递到该抽象类进行保存。第二句就是整个类中最重要的地方了,顾名思义,它的目的是通过XmlBeanDefinitionReader这个XML的Reader从资源resource中(也就是你的配置文件)读取bean的定义。接下来我们打开XmlBeanDefinitionReader的loadBeanDefinitions方法,我们可看到在这个方法里代码就一行,调用了一个同名不同参的方法,而参数是EncodedResource的一个实例,这个类实际上是Resource的一个包装类,用来保存资源的Encode的,那接下来我们再看被调用的loadBeanDefinitions方法,这个方法里最主要的部分就是:

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());}Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet<EncodedResource>(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if (!currentResources.add(encodedResource)) {throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}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);}finally {currentResources.remove(encodedResource);if (currentResources.isEmpty()) {this.resourcesCurrentlyBeingLoaded.remove();}}}


 

 

   InputSource inputSource = new InputSource(inputStream);               if (encodedResource.getEncoding() != null) {                   inputSource.setEncoding(encodedResource.getEncoding());               }       return doLoadBeanDefinitions(inputSource, encodedResource.getResource());


 

这里的目的是将资源包装成一个InputSource,连同Resource作为参数传递到doLoadBeanDefinitions方法

int validationMode = getValidationModeForResource(resource);Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());return registerBeanDefinitions(doc, resource);


这个方法的目的一目了然,就是为了将资源解释成为Document对象,然后调用registerBeanDefinitions方法,这里不做详细解释,不了解的话请去看看关于JAXP的介绍。接下来我们打开registerBeanDefinitions方法:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {// Read document based on new BeanDefinitionDocumentReader SPI.BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;}



 

0 0
原创粉丝点击