1.Spring初始
1. 为什么要学框架
学习框架相当于从"小作坊"到"工厂"的升级 , 小作坊什么都要做 , 工厂是组件式装配 , 特点就是高效.
2.框架的优点展示(SpringBoot Vs Servlet)
使用SpringBoot 项目演示框架相比 Servlet 所具备的以下优点:
- 无需配置 Tomcat , 点击"运行" 按钮就可以运行项目 , SpringBoot 内置了Web 容器(可直接运行)
- 快速添加 jar 包
- 快速发布项目(使用 java-jar 方式就可以发布)
- 对象自动装配
- …
2.Spring基础与核心概念
1.Spring 是什么?
Spring 指的是 Spring Framwork (Spring 框架) , 用一句话来说 , Spring 是包含了众多工具方法的 IoC 的容器.
1.1 什么是容器
容器是用来容纳某种物品的装置.
- List/Map -> 数据存储容器
- Tomcat -> Web 容器(存储很多 Servlet 程序)
1.2 什么是 IoC
IoC = Inversion of Control (控制反转) , 也就是说 Spring 是一个 “控制反转” 的容器 , 听上去很抽象 , 下面这个示例可以很好的解释.
传统程序开发:
假如我们开发一个车的程序 , 大致实施思路是这样的.
构建一个车(Car)需要依赖车架(Framworl) , 车架需要依赖底盘(Bottom) , 底盘需要依赖轮胎(Tire) , 代码大致如下:
public class Car {
public void init(){
Framework framework = new Framework();
System.out.println("do car");
framework.init();
}
public static void main(String[] args) {
Car car = new Car();
car.init();
}
}
public class Framework {
public void init(){
Bottom bottom = new Bottom();
System.out.println("do framework");
bottom.init();
}
}
public class Bottom {
public void init(){
Tire tire = new Tire();
System.out.println("do bottom");
tire.init();
}
}
public class Tire {
private int size = 17;
public void init(){
System.out.println("size ->>" + size);
}
}
如果我们系统升级 , 客户可以任选车轮尺寸 , 这时就会发现很大的缺陷 , 当最底层发生改变时 , 整个调用链都需要修改 , 说明代码的耦合性太强.
public class Tire {
private int size = 17;
public Tire(int size){
this.size = size;
}
public void init(){
System.out.println("size ->>" + size);
}
}
public class Bottom {
private Tire tire;
public Bottom(int size){
tire = new Tire(size);
}
public void init(){
System.out.println("do bottom");
tire.init();
}
}
public class Framework {
private Bottom bottom;
public Framework(int size){
bottom = new Bottom(size);
}
public void init(){
System.out.println("do framework");
bottom.init();
}
}
public class Car {
private Framework framework;
public Car(int size){
framework = new Framework(size);
}
public void init(){
System.out.println("do car");
framework.init();
}
public static void main(String[] args) {
Car car = new Car(25);
car.init();
}
}
那么随着系统的迭代升级 , 人们有了更多的需求 , 底层千变万化 , 我们就会发现需要耗费大量的时间去修改整个调用链 , 因此需要解耦.
解决传统开发中的缺陷
传统开发的最主要缺陷就是 , 一个模块在依赖另一个模块的同时还控制其生命周期(new 下级) , 因此当下游模块发生改动 , 上游也要跟着改 , 那么我们解决这个问题的办法就是将原来自己创建下级类 , 改为传递的方式(也就是注入的方式) , 这样当下级类发生变化 , 当前类也无需修改任何代码 , 这样就解决了程序的解耦.
解耦指的是解决了代码的耦合性 , 耦合性也可以换一种叫法叫程序相关性 , 好的代码程序的耦合性(代码之间的相关性)是很低的.
这就好比打造汽车时 , 如果所有配件都是自己造的 , 那么当客户需求发生改变的时候 , 例如修改尺寸 , 那就需要我们自己动手来改了 , 如果我们将轮胎外部出去 ,那么即使轮胎的尺寸发生变化 , 我们只需向代理工厂下订单即可.
控制反转式程序开发
基于以上思路 , 我们把调用汽车的程序示例改造一下 , 把创建子类的方式 , 改为调用子类 , 具体实现代码如下:
public class Test {
//交给 Test 这个第三方类来控制
public static void main(String[] args) {
Tire tire = new Tire(20, "白色");
Bottom bottom = new Bottom(tire);
Framework framework = new Framework(bottom);
Car car = new Car(framework);
car.init();
}
}
public class Tire {
private int size; //客户不再满足与17尺寸
private String color;//客户新增颜色需求
// 新增 尺寸 和 颜色需求
public Tire(int size, String color) {
this.size = size;
this.color = color;
}
public void init() {
System.out.println("size ->>" + size + " color ->>" + color);
}
}
public class Bottom {
private Tire tire;
public Bottom (Tire tire){
this.tire = tire;
}
public void init(){
System.out.println("do Bottom");
tire.init();
}
}
public class Framework {
private Bottom bottom;
public Framework(Bottom bottom){
this.bottom = bottom;
}
public void init(){
System.out.println("do Framework");
bottom.init();
}
}
public class Car {
private Framework framework;
public Car(Framework framework){//不再控制 Framework 的生命周期, 只使用并不关心谁创建(解耦).
this.framework = framework;
}
public void init(){
System.out.println("do cat...");
framework.init();
}
}
1.3 理解 Spring IoC
Spring IoC 核心操作:
- 将对象存入到容器中
- 从容器中取出对象
也就是说学 Spring 最核心的功能 , 就是学如何将对象存入到 Spring 中 , 再从 Spring 中获取对象的过程.
将对象放入容器的好处: 将对象存储到 IoC 容器相当于将以后可能用到的工具都放好到仓库中 , 需要的时候直接取即可 , 用完再放回到仓库中. 而 new 对象的方式相当于 , 每次需要工具的时候都要自己动手去做 (new对象) , 用完之后直接丢弃不保存(销毁对象) , 下次再用的时候还得重写去做 , 这就是 IoC 和普通程序开发的区别.
Spring 是一个 IoC 容器 , 说得是对象的创建和销毁的权利都交给 Spring 来管理了 , 它本身又具备了存储对象和获取对象的能力.
Spring IoC 的优点:
- 解耦
- 使用更加方便(无需手动创建和关注这个类对象背后的依赖关系 )
- 更加高效(类似于使用线程和线程池的区别)
如果 A 要依赖 B , 而 B 又依赖 C D E , 如果我们使用传统的开发方式 , 不但需要自己手动实现 B C D E , 而且下游的子类发生改变 , 上游的父类也要跟着改变. 但如果我们使用 Spring IoC , 无需自己手动实现依赖 , 也无需关注后续的依赖方法.
1.4 DI 概念说明
说到 IoC 就不得不提另一个词 “DI” , DI 是 Dependency Injection 的缩写 , 也就是"依赖注入".
所谓依赖注入 , 就是在 IoC 容器运行期间 , 将依赖的某个对象动态的注入到当前类的行为(主动). 所以依赖注入(DI) 和控制反转(IoC) 是从不同的角度描述了同一件事 , 就是指通过引入 IoC 容器 , 利用依赖注入的方式 , 实现对象之间的解耦.
IoC 是一种思想 , 而 DI 是一种具体的实现技术 , 也就是通过 DI (依赖注入) 来实现 IoC 思想.
例如: 学生每天会问老师很多的问题 , 老师被动的去接收问题就是传统的开发模式 , 如果老师掌握主动权 , 每天去督促学生 , 这就相当于 依赖注入.