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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

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

地址链接

源码分析

20191102100564\_1.png

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文件。

contextConfigLocation classpath:beans.xml

并将值设置(就是我们的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-scanbase-package=”com.geeekr.service,com.geeekr.dao”/
  <context:component-scanbase-package=”com.geeekr.service,com.geeekr.dao”/

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

9一眼就能看出是通过

Set 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中。

反射代理加载


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 看看spring源码一 Spring class 加载过程(源码阅读分析)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏