ClassPathXmlApplicationContext
1.为什么要分析Spring源码:
1)有意往架构上发展,分析Spring可清楚它做了哪些事情,如何做这些事情
2)Spring本身是对Java的丰富和发展,阅读可提高自己的水平
2.怎样分析Spring源码:
1)源码本身就是注释,是对平时应用的解释,所有没有必要句句分析,否则与把所有代码贴上没有区别
2)不关注相关方法所在类,接口,以及类之间的继承关系,只关注方法做了哪些事情即可
3)分析之后梳理要点
3.从ClassPathXmlApplicationContext分析开始:
1)搭建环境
利用maven命令行创建一个项目:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=myapp -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
在src/main,src/test建立resources文件,使之成为标准的maven java项目;
App.java:
package com.mycompany.app;
/**
* Hello world!
*
*/
public class App
{
public void say(){
System.out.println("App.app()");
}
}
Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<bean id="app" class="com.mycompany.app.App"></bean>
</beans>
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>myapp</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>myapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.1.3.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
利用AppTest.java:
package com.mycompany.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest{
public static void main(String[] args) {
@SuppressWarnings("resource")
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("SpringBean.xml");
App app = (App)applicationContext.getBean("app");
app.say();
}
}
利用整体目录如下:
2)Debug进行调试,refresh方法
先进入ClassPathXmlApplicationContext:
然后进入到org.springframework.context.support中的ClassPathXmlApplicationContext方法:
setConfigLocations主要是加载Spring配置文件的位置,下面分析refresh:
obtainFreshBeanFactory方法如下:它先使用refreshBeanFactory销毁Bean,BeanFactory然后分别生成BeanFactory,Bean,
然后利用getBeanFactory得到一个新生成的BeanFactory,然后返回这个BeanFactory:
loadBeanDefinitions进行Beans的读取和载入,下面可以看到找到了Spring的配置文件,并且遍历对其(这里只有
一个配置文件)进行了分析:
同时可以看到是,loadBeanDefinitions支持三种类型的参数,Properties说明Spring的配置支持properties文件,而Groovy可能与Groovy语言有关;
最后就是Bean的分析,可以看到分别调用的下面的方法:
loadBeanDefinitions -> doLoadBeanDefinitions(加载Bean) -> registerBeanDefinitions -> doRegisterBeanDefinitions(注册Bean) -> parseBeanDefinitions(分析所有Beans) ->
parseDefaultElement(分析每一个Bean元素)
我们测试时只有一个Bean,标签为<bean></bean>, 所以接着会调用下面的方法:
这样就对Spring中的所有节点<bean><import>等进行了分析。
3)源码梳理:
总的来说ClassPathXmlApplicationContext 这种形式的Spring配置文件的加载主要是下面的过程:
A:加载配置文件名到系统配置
B:销毁已有的Beans和BeanFactory
C:创建新的BeanFactory
D:加载Beans,分析Bean中的节点,然后加载到BeanFactory,BeanFactory生效。