1. 概念篇
1.1 IoC是什么?
Spring是一个包含了各种工具的IoC容器
将对象存储的在容器中用的时候直接取,用完之后再放回【单例模式】
new对象就相当于每次需要用的时候现做,用完之后就扔掉,下次使用需要重新制作
Inversion of Control「控制反转」也就是说 Spring 是一个控制反转的容器
以前我们操作对象需要 new 对象,由对象的作用域决定生命周期。使用 Spring 之后,就由框架提供了统一的容器来管理,实例化这些对象,并自动组织对象的之间的复杂依赖关系「体现在代码中就是对象中成员变量引入另一个变量」
为何叫控制反转?
从使用上看,之前的 new 对象、设置属性这些控制权限都在使用者身上;使用了 Spring容器 之后,现在全部转移到容器中,容器会自动管理组织这些对象之间的关系依赖。因为控制权限发生了反转,所以叫控制反转
该如何理解呢?
这个是传统的一辆汽车生产过程
代码实现如下
package old;
/**
* 轮胎
*/
public class Tire {
private int tireSize;
public void init(int tireSize) {
this.tireSize = tireSize;
System.out.println("Tire size:" + this.tireSize);
}
}
package old;
/**
* 底盘
*/
public class Bottom {
private Tire tire;
public Bottom() {
this.tire = new Tire();
}
public void init(int tireSize) {
tire.init(tireSize);
System.out.println("Bottom init.");
}
}
package old;
/**
* 车身
*/
public class Framework {
private Bottom bottom;
public Framework() {
this.bottom = new Bottom();
}
public void init(int tireSize) {
bottom.init(tireSize);
System.out.println("Framework init.");
}
}
package old;
public class Car {
private void init(int tireSize) {
Framework framework = new Framework();
framework.init(tireSize);
}
public static void main(String[] args) {
int tireSize = 19;
Car car = new Car();
car.init(tireSize);
}
}
//运行结果
Tire size:19
Bottom init.
Framework init.
弊端:如果想修改轮胎的花纹,刹车钳,轮毂。。。 那么就需要从 Tire 底层开始修改。由于 Bottom 依赖 Tire,Framework 依赖 Bottom。所以会导致整个供应链上的修改【耦合太高】
package v2;
public class TireV2 {
private int tireSize;
private String tireTread;
public TireV2(int tireSize, String tireTread) {
this.tireSize = tireSize;
this.tireTread = tireTread;
}
public void init() {
System.out.println("Tire size:" + tireSize);
System.out.println("Tire tread:" + tireTread);
}
}
package v2;
public class BottomV2 {
private TireV2 tireV2;
public BottomV2(TireV2 tireV2) {
this.tireV2 = tireV2;
}
public void init(){
tireV2.init();
System.out.println("BottomV2 init");
}
}
package v2;
public class FrameworkV2 {
private BottomV2 bottomV2;
public FrameworkV2(BottomV2 bottomV2) {
this.bottomV2 = bottomV2;
}
public void init(){
bottomV2.init();
System.out.println("FrameworkV2 init.");
}
}
package v2;
public class CarV2 {
private FrameworkV2 frameworkV2;
public CarV2(FrameworkV2 frameworkV2) {
this.frameworkV2 = frameworkV2;
}
public void init(){
frameworkV2.init();
System.out.println("CarV2 init.");
}
}
package v2;
public class App {
public static void main(String[] args) {
int tireSize = 17;
String tireTread = "All-Season Tread";
TireV2 tireV2 = new TireV2(tireSize, tireTread);
BottomV2 bottomV2 = new BottomV2(tireV2);
FrameworkV2 frameworkV2 = new FrameworkV2(bottomV2);
CarV2 carV2 = new CarV2(frameworkV2);
carV2.init();
}
}
//运行结果
Tire size:17
Tire tread:All-Season Tread
BottomV2 init
FrameworkV2 init.
CarV2 init.
1.2 传统开发 和 IoC 对比总结
理解传统方式:Car --> Framework --> Bottome --> Tire
上级一直在 不停的 new 下级对象 和 调用 init,整个过程是 自顶而下
package old;
public class Car {
private void init(int tireSize) {
Framework framework = new Framework();
framework.init(tireSize);
}
public static void main(String[] args) {
int tireSize = 19;
Car car = new Car();
car.init(tireSize);
}
}
理解IoC:Tire --> Bottom --> Framework --> Car
使用者会提前 new 好需要的下级对象,通过注入的方式传递给上级对象
package v2;
public class App {
public static void main(String[] args) {
int tireSize = 17;
String tireTread = "All-Season Tread";
TireV2 tireV2 = new TireV2(tireSize, tireTread);
BottomV2 bottomV2 = new BottomV2(tireV2);
FrameworkV2 frameworkV2 = new FrameworkV2(bottomV2);
CarV2 carV2 = new CarV2(frameworkV2);
carV2.init();
}
}
IoC和传统开发区别就是依赖的传递相反,不再是上级控制下级;而是通过注入的方式,下级的修改也不会影响上级
1.3 DI概念说明
上文的 IoC 提到的一个新的概念就是 依赖注入「Dependency Injection」
官方的话:所谓的依赖注入就是在 Spring 容器运行期间,动态地把某种依赖关系注入到 Spring容器
翻译过来就是:比如今天我要返校,我可以火车,大巴车,高铁,飞机等等交通工具来解决返校问题。这段话中 返校:就相当于IoC,而 交通工具 则就是 DI
IoC就比如是一种设计思想,指导原则;而 DI 就是实打实的具体方案
IoC 和 DI 从不同角度描述的同一件事:IoC 利用 DI 实现程序之间的解耦
现在我们知道了通过 DI 来把东西放入到 Spring容器 中,下一步就是如何使用。来看一下具体项目流程