spring源码阅读(一) Bean加载解析准备

作为一名java工程师,没有阅读过spring源码,总有一种要被鄙视的感觉,另外也想通过阅读源码提升自己的能力,没有比spring更合适的了。

那么开始这个源码阅读的系列吧,参考书籍《Spring源码深度解析》

2019-06-26 Spring加载的解析

首先我们构建的spring例子工程

我们主要代码:

public static void main(String args[]){
        BeanFactory context = new XmlBeanFactory(new ClassPathResource("ioc.xml"));
        Zaojiaoshu zaojiaoshu = (Zaojiaoshu) context.getBean("zaojiaoshu");
        System.out.println(zaojiaoshu.getAge() + "岁" + zaojiaoshu.getHigh() + "米");
    }

核心是这个XmlBeanFactory我们来看下它的代码,打开发现比较简单:

public class XmlBeanFactory extends DefaultListableBeanFactory {
    private final XmlBeanDefinitionReader reader;

    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, (BeanFactory)null);
    }

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

那么,构造函数里又调用了另一个构造函数。才是真正的核心。那么BeanFactory本身的结构是什么样的?通过代码可以看到主要是继承了DefaultListableBeanFactory。来看:

牵扯的内容很多,有些现在不能一一说明用意,只能粗略的了解下先。

比如:

BeanDefinitionRegistry 提供对BeanDefinition的各种增删改查操作。后续了解清楚各个组建的作用后,再来添加详细。To do ...

返回之前Main方法中继续。创建完XmlBeanFactoryBean对象时,主要参数是Resource对象。分析下:

Resource接口是spring提供的统一的资源封装接口,用来封装各种底层资源。

public interface Resource extends InputStreamSource {
    boolean exists();

    boolean isReadable();

    boolean isOpen();

    URL getURL() throws IOException;

    URI getURI() throws IOException;

    File getFile() throws IOException;

    long contentLength() throws IOException;

    long lastModified() throws IOException;

    Resource createRelative(String var1) throws IOException;

    String getFilename();

    String getDescription();
}

InputStream就更简单了。

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

获取InputStream的返回对象。

可以看到Resource接口里,提供了文件是否存在/是否可读/是否打开的方法,来判断资源状态。另外还提供了不同资源向URL/URI/File类型资源的转换方法。

看下Resource的类图结构:

为了便于显示,删除了部分AbstractResource的实现类,主要用来看下类结构图。

相关实现,就比较简单了,查看源码就能看到,比如ClassPathResource

public InputStream getInputStream() throws IOException {
        InputStream is;
        if (this.clazz != null) {
            is = this.clazz.getResourceAsStream(this.path);
        } else if (this.classLoader != null) {
            is = this.classLoader.getResourceAsStream(this.path);
        } else {
            is = ClassLoader.getSystemResourceAsStream(this.path);
        }

        if (is == null) {
            throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
        } else {
            return is;
        }
    }

借助ClassLoader或者class提供了底层方法进行调用。其他的具体查看下代码即可。核心就是能够获取资源的InputStream流。

讲了Resource,那继续之前方法中的代码:加载Bean。

Todo 把当时写在word上的内容,挪过来。

原文地址:https://www.cnblogs.com/aquariusm/p/11110465.html