zoukankan      html  css  js  c++  java
  • 01_spring源码分析-XmlBeanFactory

    Spring源码分析之BeanFactory

    献自己:

      枯燥无味的学习之路有时真的是无法静下心来苦心钻研;没有掌声,没有鲜花,只有自己内心浮躁不安。

      谨记:戒骄戒躁,潜心求知。


    一、工程代码如下:

    //实体类
    public
    class Person { private String name; public String getName() { return "Axuduo"; } public void setName(String name) { this.name = name; } }
    //测试类
    public
    class TestBean { @Test public void getPerson(){ BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-bean.xml")); Person person = (Person) beanFactory.getBean("person"); Assert.assertEquals("Axuduo",person.getName()); } }
    //配置文件:spring-bean.xml
    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="person" class="com.oops.pojo.Person"/> </beans>

    二、基础容器XmlBeanFactory

      首先将分析实例化XmlBeanFactory开始;对应代码:

    BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-bean.xml"));

      1、封装配置文件  

      时序图如下:

      归纳:测试类首先调用ClassPathResouce的构造函数,构造Resource资源文件的实例对象;将Resource对象传递给XMLBeanFactory进行实例化该对象初始化。

      那么,ClassPathResouce都做了哪些操作呢?

      其实Spring对其内部使用到的资源实现了自己的抽象结构,Resource接口封装底层资源。其中InputStreamSource接口封装任何可能返回InputStream的类,它只定义了一个方法getInputStream方法,该方法返回一个InputStream对象。

      在得到InputStream后就可以利用Resource及其子类为我们提供的特性进行后续开发了。有了Resource接口便可以对所有资源文件统一处理了。具体Resource接口如下:

    public interface Resource extends InputStreamSource {
    
        /**
         * 是否存在*/
        boolean exists();
        /**
         * 可读性*/
        default boolean isReadable() {
            return exists();
        }
        /**
         * 是否打开状态*/
        default boolean isOpen() {
            return false;
        }
        /**
         * 是否是一个文件*/
        default boolean isFile() {
            return false;
        }
        /**
         * 获取URL资源*/
        URL getURL() throws IOException;
        /**
         * 获取URI资源*/
        URI getURI() throws IOException;
        /**
         * 获取文件资源*/
        File getFile() throws IOException;
        /**
         * 取消读取*/
        default ReadableByteChannel readableChannel() throws IOException {
            return Channels.newChannel(getInputStream());
        }
        /**
         * 内容长度*/
        long contentLength() throws IOException;
        /**
         * 最后修改时间*/
        long lastModified() throws IOException;
        /**
         * 创建一个相对资源*/
        Resource createRelative(String relativePath) throws IOException;
        /**
         * 获取文件名*/
        @Nullable
        String getFilename();
        /**
         * 获取文件描述*/
        String getDescription();
    }

      当通过Resource相关类完成了对配置文件进行封装后;配置文件的读取工作就全部交给XmlBeanFactory来处理了。

      2、XmlBeanFactory

      XmlBeanFactory通过封装后的Resource进行实例化对象。代码如下:

    public class XmlBeanFactory extends DefaultListableBeanFactory {
        private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
        /**
         * 构造函数需要:Resource 对象*/
        public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, null);
        }
        /**
         * 待自身构造调用;委派至XMLBeanDeinitionReader*/
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
            super(parentBeanFactory);          // 注意父类中执行了两个或多个类的自动装配功能
            this.reader.loadBeanDefinitions(resource);
        }
    }

       3、加载Bean

      首先看一下时序图

      流程梳理:

        1、封装资源文件。当进入XMlBeanDefiinitionReader后首先对参数Resource使用EncodedResource类进行封装。

        2、获取输入流。从Resouce中获取对应的InputStream 并构造InputSource.

        3、通过构造的InputSource实例和Resouce实例继续调用函数doLoadBeanDefinitions.

      EncodeResource主要是对资源文件进行编码处理;如果有指定编码则使用指定编码;没有则采用默认。方法如下

       public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(new EncodedResource(resource));
        }

      通过上面的对资源文件的处理后将进入最核心的部位了:doLoadBeanDefinitions(InputSource inputSource,Resouce resource)

    //代码经过去除catch部位
    protected
    int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource);   // 将资源文件传缓存 document int count = registerBeanDefinitions(doc, resource);    // 执行注册 if (logger.isDebugEnabled()) { logger.debug("Loaded " + count + " bean definitions from " + resource); } return count; } }

    至此可以清晰的看见只有两部操作:1、转换Document;2、执行注册;

    到此完成注册流程。

  • 相关阅读:
    zoj 3627#模拟#枚举
    Codeforces 432D Prefixes and Suffixes kmp
    hdu 4778 Gems Fight! 状压dp
    CodeForces 379D 暴力 枚举
    HDU 4022 stl multiset
    手动转一下田神的2048
    【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律
    poj 3254 状压dp
    C++中运算符的优先级
    内存中的数据对齐
  • 原文地址:https://www.cnblogs.com/axuduo/p/11144491.html
Copyright © 2011-2022 走看看