1.为什么要学框架?
在博主之前完成的项目【手把手带你搭建个人博客系统】,并没有使用易用高效的框架,而是基于Servlet来实现的,众所周知,基于Servlet来实现项目,流程极为繁琐,不仅需要进行一些文件的配置,还需要去maven中央仓库下载版本匹配的jar包,极易出错,因此我们需要学习这些更加易用、简单且高效的框架。
学习框架相当于从“小作坊”到“工厂”的升级,小作坊什么都需要自己来做,工厂是组件式装配,特点就是高效。
2.Spring是什么?
我们通常所说的Spring指的是Spring Framework(Spring框架),它是一个开源框架,有着活跃而庞大的社区,这就是它能经久不衰的原因。
用一句话来概括Spring:Spring是包含了众多工具方法的IoC容器。
2.1 什么是容器?
容器是用来容纳某种物品的(基本)装置,在我们之前学习到的容器例如有:
List/Map ->数据存储容器
Tomcat->Web容器
2.2 什么是IoC?
Spring是一个IoC容器,那什么是IoC呢?IoC=Inversion of Control翻译成中就是“控制反转”的意思,也就是说Spring是一个“控制反转”的容器,我们从下边的示例来具体理解这句话:
2.2.1 传统程序开发
假如我们现在在构建一辆“车”的程序,我们实现的思路是这样的:
构建一辆车(Car),然而车需要依赖车身(FrameWork),而车身需要依赖底盘(Bottom),而底盘需要依赖轮胎(Tire),最终程序的实现代码如下:
public class NewCarExample { public static void main(String[] args) { Car car = new Car(); car.init(); } /** * 汽⻋对象 */ static class Car { public void init() { // 依赖⻋身 Framework framework = new Framework(); framework.init(); } } /** * ⻋身类 */ static class Framework { public void init() { // 依赖底盘 Bottom bottom = new Bottom(); bottom.init(); } } /** * 底盘类 */ static class Bottom { public void init() { // 依赖轮胎 Tire tire = new Tire(); tire.init(); } } /** * 轮胎类 */ static class Tire { // 尺⼨ private int size = 30; public void init() { System.out.println("轮胎尺⼨:" + size); } } }
在上边的代码中存在的缺陷就是,轮胎的尺寸是固定的,如果我们需要加工多种尺寸的轮胎,或者还想要对车子加上一些属性,那么就要对上面的代码做出修改了,修改后的代码如下所示:
public class NewCarExample2 { public static void main(String[] args) { Car car = new Car(); car.init(50, "猛男粉"); } /** * 汽车对象 */ static class Car { public void init(int size, String color) { // 依赖车身 Framework framework = new Framework(); framework.init(size, color); } } /** * 车身类 */ static class Framework { public void init(int size, String color) { // 依赖底盘 Bottom bottom = new Bottom(); bottom.init(size, color); } } /** * 底盘类 */ static class Bottom { public void init(int size, String color) { // 依赖轮胎 Tire tire = new Tire(); tire.init(size, color); } } /** * 轮胎类 */ static class Tire { // 尺寸 // private int size = 30; public void init(int size, String color) { System.out.println("轮胎尺寸:" + size + " | 颜色:" + color); } } }
从上边的代码中可以看出的问题是:在最底层的代码改动之后,整个调用链上的代码都需要发生变动。
上边问题产生的原因是我们在每个类中自己创建下级类,才导致如果下级类发生改变操作,自己也需要跟着变;
我们将原来由自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦。
2.2.2 控制反转式程序开发
基于上述的思路,我们把构造汽车的代码改造一下,把创建子类的方式,改为注入传递的方式,具体实现代码如下:
public class IocCarExample { public static void main(String[] args) { Tire tire=new Tire(50,"猛男粉"); Bottom bottom=new Bottom(tire); Framework framework=new Framework(bottom); Car car=new Car(framework); car.run(); } static class Car { private Framework framework; public Car(Framework framework) { this.framework = framework; } public void run() { framework.init(); } } static class Framework { private Bottom bottom; public Framework(Bottom bottom) { this.bottom = bottom; } public void init() { bottom.init(); } } static class Bottom { private Tire tire; public Bottom(Tire tire) { this.tire = tire; } public void init() { tire.init(); } } static class Tire { private int size; private String color; public Tire(int size, String color) { this.size = size; this.color = color; } public void init() { System.out.println("轮胎:"+size+"| 颜色:"+color); } } }
经过以上代码调整,无论底层类如何变化,整个调用链不需要做变动,这样就完成了代码的解耦,从而实现了更加灵活、通用的程序设计了。
2.2.3 对比规律总结
在传统代码中对象的创建顺序是:
Car-> Framework -> Bottom -> Tire
改进后解耦代码的对象的创建顺序刚好与之相反,就是通过这样的改进,完成了控制权的反转,不再是上级对象创建并控制下级对象了,而是下级对象注入当前对象中,下级的控制权不再由上级类控制,这样即使下级类发生任何改变,当前类是都不受影响的,这就是典型的控制反转,也就是IoC的实现思想。
2.3 理解Spring IoC
Spring是包含了众多工具方法的IoC容器,通过IoC的实现,实现了代码的解耦;对象(Bean)的生命周期交由IoC框架来维护,作为程序员就无需再关注了。
Spring IoC容器最核心的功能:
1.将Bean(对象)存储到Spring(容器)中。
2.将Bean(对象)从Spring(容器)中取出来。
Spring是一个IoC容器,对象的创建和销毁的权利都交给Spring来管理了,它本身又具备了存储对象和获取对象的能力。
2.4 什么是DI?
DI 是 Dependency Injection 的缩写,翻译成中⽂是“依赖注⼊”的意思。
依赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。
IoC是一种思想,而DI是具体的实现
就想比如说我今天想去外边吃一顿好的,那么吃一顿好的是思想和目标(IoC),但最后是去吃海底捞还是烧烤?这就是具体的实现,就是DI。
3.总结
Spring是什么?如何理解Spring?
IoC和DI是什么?有什么区别?
Spring最核心的功能是啥?