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、执行注册;

    到此完成注册流程。

  • 相关阅读:
    黄聪:WordPress wp_head()优化:去除不必要的元素标签(转)
    黄聪:IE6下用控制图片最大显示尺寸
    黄聪:wordpress wp_head()函数 浏览器顶部 空白28px 解决办法(转)
    黄聪:在Photoshop中创建多种样式的网格背景图案(转)
    黄聪:如何WP中获取文章分类名称、分类ID、归档分类链接
    黄聪:Wordpress如何不显示(只显示)置顶文章
    黄聪:淘宝用户在宝贝详情页想看到什么
    黄聪:Windows7立体声混音设置方法(stereo mix)(转)
    黄聪:wordpress博客用Slimbox2实现lightbox效果(免插件)(转)
    黄聪:tor 解决 连接中继目录failed 没有可用的链路
  • 原文地址:https://www.cnblogs.com/axuduo/p/11144491.html
Copyright © 2011-2022 走看看