美文网首页
spring解析xml(二)解析相关结构

spring解析xml(二)解析相关结构

作者: guessguess | 来源:发表于2020-06-29 11:35 被阅读0次

1.测试方法代码

public class Config {
    
    public static void main(String args[]) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:application-config.xml");
        System.out.println(applicationContext.getBean(HelloService.class).sayHello());
    }
}

2.什么是application。
application就是我们所谓的上下文,容器。
FileSystemXmlApplicationContext是application的一个具体实现。spring中有许多application的不同实现,如ClassPathXmlApplicationContext,AnnotationConfigApplicationContext。下面我们先从FileSystemXmlApplicationContext开始入手。

3.结构如图所示


image.png

从上图的结构来看。其实整个容器是由几部分组成的。分别为ResourceLoader, BeanFactory, ApplicationEventPublisher, EnvironmentCapable, Lifecycle, Closeable。

分别介绍几个概念,ResourceLoader资源加载器,其中我们的类,class文件其实便是资源,资源加载器就是负责去加载资源, 至于根据什么去找到资源,那便是路径。那么有ResourceLoader便会有Resouce,那么resouce怎么跟bean关联起来呢,ResourceLoader便是将加载到的resouce转换成beandefinition, 最后再注册到beanfactory中去。这里只是讲解一下概念,后续会细致一点讲。

AbstractApplicationContext是一个核心抽象类,实现了大部分的功能,剩下的交由子类去实现。

4.可能3讲的很抽象,那么下面从代码入手吧。
先看会之前的测试代码

public class Config {
    
    public static void main(String args[]) {
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:application-config.xml");
        System.out.println(applicationContext.getBean(HelloService.class).sayHello());
    }
}

为什么选择FileSystemXmlApplicationContext呢,其实AbstractXmlApplicationContext有多个实现类,所以随便挑一个进行讲解,其实ClassPathXmlApplicationContext也是大体功能是一样的。

那么好了,进入主题,先从构造方法入手吧。


/**
     * Create a new FileSystemXmlApplicationContext, loading the definitions
     * from the given XML file and automatically refreshing the context.
     * @param configLocation file path
     * @throws BeansException if context creation failed
     */
    public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }


/**
     * Create a new FileSystemXmlApplicationContext with the given parent,
     * loading the definitions from the given XML files.
     * @param configLocations array of file paths
     * @param refresh whether to automatically refresh the context,
     * loading all bean definitions and creating all singletons.
     * Alternatively, call refresh manually after further configuring the context.
     * @param parent the parent context
     * @throws BeansException if context creation failed
     * @see #refresh()
     */
    public FileSystemXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);//此处主要作用是将自身作为一个路径解析器的变量,并且注入到父类中
        setConfigLocations(configLocations);//此处是将路径保存到父类中去
        if (refresh) {//是否需要刷新
            refresh();//刷新容器---这里其实才是核心逻辑
        }
    }

先从构造方法参数的定义来看public FileSystemXmlApplicationContext(String configLocation),该构造方法上方的注解,创建一个新的FileSystemXmlApplicationContext,从码农给予的xml文件加载definitions,并且自动刷新容器。definitions其实是bean的一个包装类,记载了bean的相关信息。

接下来看其内部调用的构造方法,public FileSystemXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)。这里总共分为三个方法讲解,分别为 super(parent), setConfigLocations(configLocations), refresh()

首先从super(parent)看起

public FileSystemXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {

        super(parent);//此处主要作用是将自身作为一个路径解析器的变量,并且注入到父类
        。。。。。。下面的代码暂时忽略
    }
最终到达的父类AbstractApplicationContext位置,this是一开始新建的FileSystemXmlApplicationContext实例

AbstractApplicationContext中的
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext{
    private ResourcePatternResolver resourcePatternResolver;
    public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }
    protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }
}

那么PathMatchingResourcePatternResolver类的结构是怎么样的呢?
public class PathMatchingResourcePatternResolver{
    private final ResourceLoader resourceLoader;
    public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
        Assert.notNull(resourceLoader, "ResourceLoader must not be null");
        this.resourceLoader = resourceLoader;
    }
}

根据代码,最后发现,FileSystemXmlApplicationContext实例将自己包装成PathMatchingResourcePatternResolver并且注入到AbstractApplicationContext中去。这里为什么FileSystemXmlApplicationContext实例可以包装成路径匹配资源解析器呢?因为AbstractApplicationContext本身是FileSystemXmlApplicationContext的父类,同时AbstractApplicationContext也是ResourceLoader的子类。其实说白了就是,基本的功能都是在AbstractApplicationContext中实现的,而FileSystemXmlApplicationContext实例将自己包装成资"源路径匹配资源解析器"最后又注入到AbstractApplicationContext中去。这么做的好处是,当FileSystemXmlApplicationContext改变了某些逻辑的时候,代码可以不用做任何调整。

其次是setConfigLocations(configLocations),这段代码便是将解析后的路径,注入到AbstractRefreshableConfigApplicationContext的成员变量configLocations中去。

最后讲解的是核心refresh(),篇幅有点长,放下一篇吧。

相关文章

网友评论

      本文标题:spring解析xml(二)解析相关结构

      本文链接:https://www.haomeiwen.com/subject/ofuptktx.html