【Spring源码分析】预备篇
前言
最新想学习一下Spring源码,开篇博客记录下学习过程,欢迎一块交流学习。
作为预备篇,主要演示搭建一个最简单的Spring项目样例,对Spring进行最基本梳理。
构建一个最简单的spring项目
Spring中最核心的Jar包有四个:spring-beans、spring-context、spring-core、spring-expression。
以前做spring项目有个误区,什么包都一个个导入进来,其实一个最最简单的Spring项目,理论上就需要引入一个jar包spring-context就够了,靠它的依赖关系,其他核心包都会自动导入进来(只是核心包,实际真实项目需要其他功能再额外导入)。
1、在一个空项目里 添加Spring项目模块 Maven->jdk1.8>webapp 模板
2、这里在pom中只额外添加 spring-context依赖
(它依赖其他几个核心jar包 会自动导入依赖)
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>5.1.3.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>
实际引入的包及依赖关系:
package cn.eport.jason.bean;
@Component
public class Student {
private String username = "WPC";
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
写一个测试方法,(因为本例中是在源代码下编写的单元测试,所以需要先在pom中去掉Junit 作用域为test的限制,不然在业务代码区使用@Test注解时会提示找不到)
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!--<scope>test</scope>-->
</dependency>
MyTest.java 测试类
package cn.eport.jason.test;
import cn.eport.jason.bean.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
@Test
public void Test1(){
//基于注解的方式加载Spring容器
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("cn.eport");
Student student =(Student) applicationContext.getBean("student");
System.out.println(student.getUsername());
}
}
运行单元测试方法Test1 控制台输出结果:
D:\DevTool\Java\jdk1.8.0_101\bin\java.exe ... cn.eport.jason.test.MyTest,Test1 WPC Process finished with exit code 0
说明Spring ioc容器功能已生效,已属于spring项目。
spring容器启动的4种方式
1、类路径获取配置文件加载容器
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring.xml");
2、文件系统路径获取配置文件【绝对路径】不常用
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("E:\\idea\\public\\springdemo\\src\\main\\resources\\spring.xml");
3、无配置文件加载容器(注解方式) 单元测试中常用
ApplicationContext applicationContext = new AnnotationConfigApplicationContext("cn.eport");
4、springboot加载容器
ApplicationContext applicationContext = new EmbeddedWebApplicationContext();
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 方式1、批量注册 包扫描+注解 -->
<context:component-scan base-package="cn.eport"/>
<!-- 方式2、手动注册bean 。 id不写 默认为类全限定名--> <bean class="cn.eport.jason.bean.Student"> </bean> </beans>
这里通过两种方式注册了Student实例:
- 一个ComonentScan扫描+注解的方式(BeanName默认类名小写)
- 一个配置注册bean的方式(默认BeanName为类全限定名)
ps:<context:component-scan>这种带有前缀的标签 为自定义标签,spring原始组件只有 spring-core和spring-bean ,常用的context、aop、tx组件其实都是扩展组件,Spring靠的就是自定义标签在核心组件上扩展使得spring更加强大,在配置文件中使用扩展标签需要引入相应的xsd;在标签对应的jar包下面找到对应的spring.schemas,在这个文件中就会有对应的XSD路径和命名空间xmlns(xml namespaceUri) (类似于java中的Import)
2、编写对应的测试方法 使用 ClassPathXmlApplicationContext 读取配置文件加载容器获取bean对象 进行测试:
@Test
public void Test2(){
//读取类路径下xml配置文件的方式加载spring容器
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring.xml");
Student student1 =(Student) applicationContext.getBean("student");//取得为包扫描+注解 方式注册的 beanId是类名小写
Student student2 =(Student) applicationContext.getBean("cn.eport.jason.bean.Student");//取得为配置文件中缺省id 的那个bean
System.out.println(student1.getUsername());//WPC
System.out.println(student2.getUsername());//WPC
System.out.println(student1==student2);//false 不同的注册方式注册的两个不同的实例对象
}
结果:
WPC WPC false Process finished with exit code 0
Spring容器一样也加载成功了,由此可以看出项目中只添加Spring-context 的依赖,一个最基础的Spring的项目即可搭建好(这里说的不是SpringMVC工程)
根据测试打印结果可以发现个问题,程序并没有打印出Spring的日志,原因为pom中未添加spring日志依赖logback:
<!--一个空的spring工程是不能打印日志的,要导入spring依赖的日志jar-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>LATEST</version>
</dependency>
再次执行下测试方法,控制台打印出Spring的日志:
由此,构建一个带日志的最基础Spring项目,只需要在pom中添加context、logback两个依赖即可
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!--一个空的spring工程是不能打印日志的,要导入spring依赖的日志jar-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>LATEST</version>
</dependency>
但是实际上由于jar包相互依赖,项目中maven会自动导入其他依赖,实际导入的包远远不止这两个:
实际导入的包及依赖关系如下:

结语
作为开篇内容相对简单些,经过演示我们看到了pom中只添加context、logback两个依赖就可以搭建一个带日志最基本的spring项目,以及我们知道了spring源码的入口类,后续我们进行源码分析~
【Spring源码分析】预备篇的更多相关文章
- spring源码分析---事务篇
上一篇我介绍了spring事务的传播特性和隔离级别,以及事务定义的先关接口和类的关系.我们知晓了用TransactionTemplate(或者直接用底层P的latformTransactionMana ...
- Spring 源码分析 spring-core 篇
先来看下 spring-core 的包结构 总共有6个模块,分别是 asm.cglib.core.lang.objenesis.util asm包: 用来操作字节码,动态生成类或者增强既有类的功能.主 ...
- spring源码分析之spring-core总结篇
1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...
- Spring源码分析——BeanFactory体系之抽象类、类分析(二)
上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...
- Spring源码分析——BeanFactory体系之抽象类、类分析(一)
上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口. 一.BeanFactor ...
- Spring源码分析——资源访问利器Resource之实现类分析
今天来分析Spring的资源接口Resource的各个实现类.关于它的接口和抽象类,参见上一篇博文——Spring源码分析——资源访问利器Resource之接口和抽象类分析 一.文件系统资源 File ...
- spring源码分析(二)Aop
创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...
- 【Spring源码分析】非懒加载的单例Bean初始化前后的一些操作
前言 之前两篇文章[Spring源码分析]非懒加载的单例Bean初始化过程(上篇)和[Spring源码分析]非懒加载的单例Bean初始化过程(下篇)比较详细地分析了非懒加载的单例Bean的初始化过程, ...
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- 【spring源码分析】IOC容器初始化(七)
前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...
随机推荐
- ReentrantLock源码解析——虽众但写
在看这篇文章时,笔者默认你已经看过AQS或者已经初步的了解AQS的内部过程. 先简单介绍一下ReentantLock,跟synchronized相同,是可重入的重量级锁.但是其用法则相当不同,首先 ...
- 了解1D和3D卷积神经网络 | Keras
当我们说卷积神经网络(CNN)时,通常是指用于图像分类的2维CNN.但是,现实世界中还使用了其他两种类型的卷积神经网络,即1维CNN和3维CNN.在本指南中,我们将介绍1D和3D CNN及其在现实世界 ...
- vue动态定义图片路径
当我在html模块或者css中引入图片的时候用相对路径,例: <div> <img src="../../assets/img/policeImg/tt.png" ...
- Typora+markdown 最常用语法教程
Typora+markdown 最常用语法教程(by 程序员宝藏) Typora+markdown 最常用语法教程(by 程序员宝藏) 请先配置推荐配置(文件->偏好设置): 文章目录 Typo ...
- Python python 函数参数:可变参数
# 可变参数 '''传入的参数数量是不确定的 ''' '''若是要计算几个数(未知)的平方和 ''' def cal(nums): sum = 0 for num in nums: sum = sum ...
- 【cs224w】Lecture 3 - Motif, Graphlet 及 结构性角色
目录 Network Motifs Configuration Model Graphlets How to Find Motifs and Graphlets Structural Roles 转自 ...
- MiniUi遇到的一个Bug或者说坑,以div里面的内容自适应高度
页面源码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...
- Python学习-第三节part1: 关于函数
一 为何要用函数之不用函数的问题 #1.代码的组织结构不清晰,可读性差 #2.遇到重复的功能只能重复编写实现代码,代码冗余 #3.功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护 ...
- 数据结构与算法复习-----leetcodeOJ题解
Isomorphic Strings Given two strings s and t, determine if they are isomorphic. Two strings are isom ...
- Coding 是门技术
今天的分享来源于工作中的点点滴滴…… 01. 习惯性自嘲 代码写久了,伴随肩疼头痛眼近视,于是乎也就成了名副其实的 code farmer(码农),作为如牛吃草挤奶般的码农,吃草(撸)挤奶(码)便是日 ...