Spring5源码分析之IOC-跟踪ClassPathXmlApplicationContext-(3)

了解一个框架最好的方式就是阅读源码。源码面前,了无秘密。阅读源码是很辛苦和烦恼的一件事情,尤其是这种复杂框架的源码。阅读起来给人一种如坠五里云雾的感觉,伸手不见五指。我们在第一次阅读源码的时候一定要坚持一个原则:不计较一城一地
的得失,首先要从大局观上对Spring5有个模糊的认识,然后在后面有时间的时候,继续去抠那些个细节。Spring5的设计绝对精彩。下面就从一个最基本的例子去跟踪源码。
既然我们使用的是ClassPathXmlApplicationContext这个类来剖析Spring5的源码,那么就开始跟踪ClassPathXmlApplicationContext的具体执行,切记一点:开始阅读不要深入敌后,以免全军覆没。

工欲善其事必先利其器,我们先给出来一个我们自己写的类的例子。

public class XMLParseService{
    private String name;

    public XMLParseService() {
        System.out.println("xmlParser:使用了lazy-init参数,设置为true,开始初始化对象...");
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("xmlParser设置了name属性为:" + name);
    }

    public String parseHead(String context) {
        return "xml:";
    }
}

XML的配置如下:


    

测试跟踪代码如下:

@Test
    public void gainContext() {
        ApplicationContext context = new ClassPathXmlApplicationContext("./spring.xml");
        ParseService xmlParseService = context.getBean(XMLParseService.class);
        logger.info("Information:{}", xmlParseService.parseHead("<>"));
    }

下面开始跟踪:ApplicationContext context = new ClassPathXmlApplicaitonContext("./spring.xml")这句话,因为,一共三行代码,第三行还是一个打印日志的东西,可以忽略不计打印的作用,我们就关注到ApplicationContext的获取这行。
我们会看到,代码的执行顺序如下:
1.代码如下:

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }

这步没啥说的,就是一个调用本身的其他构造方法
2.第二步跟踪:

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

        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

这步稍微复杂些,具体解析下:super(parent) 是调用父类的构造方法,继续往上跟踪这个super方法可以看到,这个方法就是做了下面两件事情:
-设置了resourcePatternResolver(资源模式解析)
-设置了parent属性
接着setConfigLocations方法的作用:使用上面的resourcePatternResolver对你传入的资源的地址进行处理下,比如去除两头空格,以及解析你前面写的其他特殊字符什么的,这个先不看。反正目的就是:处理之后的资源地址都是干净和纯净的地址。

下面一步最重要,也是整个Spring的核心部分:refresh方法,这个方法是在最顶层的类AbstractApplicationContext实现的。下面一篇文章看具体的refresh方法的实现。
这个地方就不得不谈一谈Spring的设计模式的使用了,在这里使用了模板模式:说白了就是父类定义好了具体要做的事情,做事情肯定是分很多步骤,那么父类就把步骤给定好,只能按照这么做了,下面的子类再根据自己的具体实际情况来实现自己的具体做法部分。不过这里面有个度的问题:如果父类定步骤定的太死,那么父类就管的事情多,造成代码臃肿不堪,难以维护。并且下面的子类显得很鸡肋,因为几乎全部的工作父类都干了,还要子类干啥子。如果父类定义的步骤过于宽松,例如:定义成:开始-->操作-->结束。那就等于没说,如果这样子就不需要父类了,直接各个子类干事情就行了。并且模板模式一般是对付有复杂业务步骤的情景,如果不是过于复杂,这个模式慎用。

你可能感兴趣的:(Spring5源码分析之IOC-跟踪ClassPathXmlApplicationContext-(3))