看看spring源码一 Spring class 加载过程(源码阅读分析)

http://geeekr.com/read-spring-source-1-how-to-load-bean/ 

地址链接

源码分析

《看看spring源码一 Spring class 加载过程(源码阅读分析)》

org.springframework.web.context.ContextLoaderListener初始化IOC容器的。

 

public class ContextLoaderListener extends ContextLoader implements ServletContextListener

 

initWebApplicationContext方法是在org.springframework.web.context.ContextLoader类里面。方法太长,分段读一下。

首先是初始化initWebApplicationContext容器

 

首先determineContextClass()方法查明具体的Context类,他会读取servletContext的初始化参数contextClass,此参数我们一半不配置,所以Spring就会读取跟org.springframework.web.context.WebApplicationContext同一个包下面的ContextLoader.properties文件读取默认设置,反射出org.springframework.web.context.support.XmlWebApplicationContext类来。接下来就是在configureAndRefreshWebApplicationContext()方法里将新创建的XmlWebApplicationContext进行初始化。首先会设置一个默认ID,即org.springframework.web.context.WebApplicationContext:+你项目的ContextPath。

 

紧接着就是将ServletContext设置成XmlWebApplicationContext的属性,这样Spring就能在上下文里轻松拿到ServletContext了。

 

接下来就是读取web.xml文件中的contextConfigLocation参数。如果没有配置就会去读WEB-INF下的applicationContext.xml文件。

 

 

 

<context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:beans.xml</param-value>

</context-param>

 

并将值设置(就是我们的Spring配置文件的路径)进XmlWebApplicationContext中。然后就会在指定的路径加载配置文件。

String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);

if (configLocationParam != null) {

    wac.setConfigLocation(configLocationParam);

}

1初始化initWebApplicationContext 容器

 2创建XmlWebApplicationContext进行初始化 ServletContext设置成XmlWebApplicationContext的属性 Spring拿到ServletContext里面的内容

 3就是拿到web.xml文件中的contextConfigLocation参数。如果没有配置就会去读WEB-INF下的applicationContext.xml文件。

4接下来就是初始化BeanFactory,是整个refresh()方法的核心,其中完成了配置文件的加载、解析、注册

5根据web.xml文件中的contextConfigLocation参数下的路径解析xml文件

6这里会根据不同的XML节点,会委托NamespaceHandlerSupport找出合适的BeanDefinitionParser,如果我们配置了

 

<context:component-scan
base-package=”com.geeekr.service,com.geeekr.dao” /

8通过它去扫描包中的类文件,注意:这里是类文件而不是类,因为现在这些类还没有被加载,只是ClassLoader能找到这些class的路径而已。到目前为止,感觉真想距离我们越来越近了。顺着继续往下摸。进入doSacn方法里,映入眼帘的又是一大坨代码,但是我们只关心观点的部分。

9一眼就能看出是通过

Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

有时候不得不佩服这些外国人起名字的功力,把扫描出来的类叫做candidates(候选人);真是不服不行啊,这种名字真的很容易理解有不有?哈哈,貌似扯远了。继续往下看。这里只列出方法的主题部分。

10假设我们配置的需要扫描的包名为com.geeekr.service,那么packageSearchPath的值就是classpath*:com.geeekr.service/**/*.class,意思就是com.geeekr.service包(包括子包)下所有class文件;如果配置的是*,那么packageSearchPath的值就是classpath*:*/**/*.class。这里的表达式是Spring自己定义的。Spring会根据这种表达式找出相关的class文件。

11这里会先判断表达式是否以classpath*:开头。前面我们看到Spring已经给我们添加了这个头,这里当然符合条件了。接着会进入findPathMatchingResources方法。在这里又把**/*.class去掉了,然后在调用getResources方法,然后在进入findAllClassPathResources方法。这里的参数只剩下包名了例如com/geeekr/service/

12真相大白了,Spring也是用的ClassLoader加载的class文件。一路追踪,原始的ClassLoader是Thread.currentThread().getContextClassLoader();。到此为止,就拿到class文件了。

Spring会将class信息封装成BeanDefinition,然后再放进DefaultListableBeanFactory的beanDefinitionMap中。

反射代理加载

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/lw18781108072/article/details/85196601
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞