为什么要学框架?
- 框架相当于从小作坊,到工厂的升级,servlet什么都要自己做,而这里的框架是组件式装配,高效。
- 框架更加易用、简单且高效。
Spring是什么?
我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架,有着活跃而庞大的社区,这就是它之所以能长久不衰的原因。Spring 支持广泛的应用场景,它可以让 Java 企业级的应用程序开发起来更简单。
一句话概括 Spring:Spring 是包含了众多工具方法的 IoC 容器。
什么是容器
容器是用来容纳某种物品的(基本)装置。
- List / Map :数据存储容器
- Tomcat:包含众多web项目的web容器
- 线程池
…
什么是IoC
Spring 也是一个容器,是一个 IoC 容器。
IoC( Inversion of Control):控制反转(控制权的反转)
Spring 是一个控制反转(IoC)的容器。
实例分析
在上述代码中,展示了一个简单的类依赖关系结构,其中Car类依赖于Framework类,Framework类依赖于Bottom类,Bottom类依赖于Tire类。
当运行Car类的main方法时,程序的执行顺序如下:
- Car对象被创建,构造函数Car(int size)被调用。
- 在Car的构造函数中,Framework对象被创建,并传入参数size。同时,Car构造函数中调用Framework的构造函数。
- 在Framework的构造函数中,Bottom对象被创建,并传入参数size。同时,Framework构造函数中调用Bottom的构造函数。
- 在Bottom的构造函数中,Tire对象被创建,并传入参数size。同时,Bottom构造函数中调用Tire的构造函数。
- 当所有对象都被正确创建后,Car对象调用其init()方法。
- 在Car的init()方法中,首先打印"do car",然后调用Framework的init()方法。
- 在Framework的init()方法中,首先打印"do framework",然后调用Bottom的init()方法。
- 在Bottom的init()方法中,首先打印"do bottom",然后调用Tire的init()方法。
- 在Tire的init()方法中,打印"do tire size : " + size。
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(20);
car.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 Bottom {
private Tire tire;
public Bottom(int size) {
//依赖轮胎
tire = new Tire(size);
}
public void init() {
System.out.println("do bottom");
tire.init();
}
}
public class Tire {
private int size = 17;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("do tire size : " + size);
}
}
以上程序的问题是:当最底层代码改动之后,整个调⽤链上的所有代码都需要修改。
如何修改:
将原来创建的下级类,改为传递的方式(注入),不需要再在当前类中创建下级类,所以即使下级类发生变化,当前类也无需修改任何代码,这样就完成了程序的解耦。
public class Car {
private Framework framework;
public Car(Framework framework) {
this.framework = framework;
// framework = new Framework();
//不 new ,不创建,我不再控制 framework
}
public void init() {
System.out.println("do car...");
framework.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 Bottom {
private Tire tire;
public Bottom(Tire tire) {
this.tire = tire;
}
public void init() {
System.out.println("do bottom..");
tire.init();
}
}
public class Tire {
private int size = 17;
public Tire(int size) {
this.size = size;
}
public void init() {
System.out.println("do tire size = " + size);
}
}
public class 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();
}
}
IoC不是一个具体的技术,是一个思想,将控制权交给别人的都可以称为IoC
传统new对象的方式创建顺序:
Car -> Farmework -> Bottom -> Tire
IoC类的创建顺序:
Tire -> Bottom -> Farmework -> Car
控制权的反转
总结
Spring 是一个 包含了众多方法的IoC 容器。
IoC( Inversion of Control):控制反转(控制权的反转)
控制权的反转可以理解为:A对象本来需要new 一个B对象,管理B对象的生命周期(也就是A对象掌握了B对象的控制权),现在A部管理B对象,交由其他人管理,对于A来说就是控制权的反转(IoC)。
结合具体实例来说,传统代码是 Car 控制并创建了 Framework,Framework 控制并创建了 Bottom,依次往下。
改进之后的控制权的反转,不再是上级对象创建并控制下级对象了,而是下级把对象注入将当前对象中,下级的控制权不再由上级类控制,这样即使下级类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。
总的来说,Ioc意味着将设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。
Spring IoC
Spring 是包含了多个工具方法的 IoC 容器
Spring IoC 核心(基础)操作:
- 将对象存入容器
- 从容器中取出对象
对象:bean
容器:Spring
将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能用的所有工具制作好都放到仓库中,需要的时候直接取就行了,用完再把它放回到仓库。
而 new 对象的方式相当于,每次需要工具了,才现做,用完就扔掉了也不会保存,下次再用的时候还得重新做,这就是 IoC 容器和普通程序开发的区别。
拥有权 – > 使用权
Spring IoC的优点:
- 解耦
- 使用更加方便(不再需要手动创建,和关注这个对象背后的依赖关系)
- 更加高效
Spring 是⼀个 IoC 容器,对象的创建和销毁的权利都交给 Spring 来管理了,它本身又具备了存储对象和获取对象的能力。
在传统的面向对象编程中,对象的创建通常是通过new关键字手动完成的,程序员需要自行管理对象的生命周期(如创建、初始化、销毁等)。而在Spring中,IoC容器负责这些任务。Spring根据配置文件或注解,自动创建对象并管理其生命周期。在适当的时候,Spring还会自动销毁对象。
对象的创建:当Spring容器启动时,它会根据配置文件或注解来加载定义的Bean,并创建这些对象。对象的创建过程可能包括实例化对象、注入依赖项、调用初始化方法等。
对象的销毁:Spring也会在适当的时机销毁对象,例如在容器关闭时。Spring容器可以调用销毁方法来清理资源或执行其他必要的操作。
DI
DI (Dependency Injection):依赖注入。
所谓依赖注入,就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中。【将依赖的某个对象,注入(拿)到当前的类当中的行为,就叫做依赖注入。】
依赖注入(DI)和控制反转(IoC)是从不同的角度的描述的同⼀件事情,就是指通过引入IoC 容器,利用依赖关系注入的方式,实现对象之间的解耦。
IoC 是 “目标” ,也是⼀种思想,目标和思想只是⼀种指导原则,最终还是要有可行的落地方案,而 DI就属于具体的实现技术。
IoC :思想
Spring IoC :框架
DI:技术
上面car2例子的对象:被动传递
DI(依赖注入):主动获取对象,DI会动态的从spring中获取想要的对象