目录
我们经常说的Spring是指Spring框架(也就是轻量级Java开发框架),Spring目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合性问题,Spring最根本的使命就是为了解决企业级应用开发的复杂性
对于Spring我们可以用一句话来概括 : Spring是包含了众多工具方法的 IOC 容器;
容器 最基本的概念就是 容纳某种物品的一种基本的装置.对于程序来说,容器可以用来放入对象,取对象,所以容器也要管理对象的生命周期.
容器很常见 比如我们再学集合的时候 : List,Stack,Queue,LinkedList,Map.......等等这些是用来存储数据的,也叫作数据存储容器
再比如 : 我们在学习Tomcat ,Tomcat就是一个Web容器,里面可以放入多个Webapp(网站)......
IOC 英文 为 Inversion of Control 也就是控制反转的意思.是一种设计思想
我们先来简单地介绍一下IOC:
就比如 : 我们在使用类的时候,通常我们A类要使用B类的时候是怎么做的呢??
- //伪代码
- //A类
- class A {
- //现在A类要使用B类-->一般在A类要使用B类就需要new B()
- B b = new B();
- }
- //B类
- class B{
-
- }
很显然,我们一般写代码的时候,如果要在A类中要使用B类,那就是要new B类的.也就是A类是要依赖于B类的
对于这种就是直接在A对象的内部通过new 进行创建对象,程序主动去创建依赖的对象,也就是A类会控制B类的生命周期,比如 什么时候创建,销毁等等...
之前是A类里面要使用B类,就需要在A对象的内部创建B,也就是A类控制了B类的生命周期(创建,销毁....),对于IOC而言,A类不在对象内部创建B,而是将控制权反转,交给自己的上层,让上层把资源给我,A只需告诉上层(也就是调用我的人),我需要依赖啥资源,上层就提供啥资源,A类就直接可以用他所依赖的资源了,至于这个资源怎么来的,A并不关注.此时调整参数,对A没有任何影响,因为控制权不在于A,在与上层(也就是调用我的人).
可能还是不理解, 我们来具体举一个例子:
对于这一辆车来说,汽车依赖于车身,车身依赖于底盘,而底盘又依赖于轮胎,最终这样一辆车就做好了.
利用代码实现:
- /**
- * 启动类
- */
- public class App {
- public static void main(String[] args) {
- Car car = new Car();
- car.init();
- }
- }
- /**
- * 一辆车
- */
- public class Car {
- private FrameWork frameWork;
-
- public Car(){
- frameWork = new FrameWork();
- }
-
- //运行
- public void init(){
- //汽车的运行要依赖于车身的
- System.out.println("Car init();");
- frameWork.init();
- }
- }
-
- /**
- * 车身
- */
- public class FrameWork {
-
- private Bottom bottom;
-
- public FrameWork(){
- bottom = new Bottom();
- }
-
- public void init(){
- //车身依赖于底座
- System.out.println("FrameWork init()");
- bottom.init();
- }
- }
- /**
- * 底盘
- */
- public class Bottom {
-
- private Tire tire;
-
- public Bottom(){
- tire = new Tire();
- }
-
- public void init(){
- //底座要依赖于轮胎的
- System.out.println("Bottom init()");
- tire.init();
- }
- }
- /**
- * 轮胎
- */
- public class Tire {
-
- private int size = 17;//轮胎大小
-
- public void init(){
- System.out.println("Tire Size : " + size);
- }
- }
上面一辆车我们就制造好了,但是突然有一天产品提一个需求,轮胎的大小我要是自定义的,也就是用户想要多大我们就给大做多大.
可以看到当我们用户需求变了,轮胎尺寸变为动态的时候,调用底层的上层类都需要修改代码.对于企业来说,项目会有几千个类,几万个类...可见是很难去维护的.
对于上面的程序是由底层控制上上层的.当我们修改底层类,调用底层的所有上层类,都会去修改.
此时,我们可以实现控制反转,我们想办法不再由下层控制着上层,也就是让上层控制着下层,将控制权反转一下.
对于当前类来说,我不在自己创建了,而是交给我的调用者去创建,我只把我想要的资源拿来用就可以了.
- public class App {
- public static void main(String[] args) {
- int size = 34;
- Tire tire = new Tire(size);
- Bottom bottom = new Bottom(tire);
- FrameWork frameWork = new FrameWork(bottom);
- //初始化一辆车
- Car car = new Car(frameWork);
- car.init();
- }
- }
-
- public class Car {
- private FrameWork frameWork;
- //现在我不自己创建了,我只拿到我想要的资源就可以了,资源怎么做的我不管
- public Car(FrameWork frameWork){
- this.frameWork = frameWork;
- }
- public void init(){
- System.out.println("Car init()");
- frameWork.init();
- }
- }
- public class FrameWork {
- private Bottom bottom;
-
- //现在我不自己创建了,我只拿到我想要的资源就可以了,资源怎么做的我不管
- public FrameWork(Bottom bottom){
- this.bottom = bottom;
- }
- public void init(){
- System.out.println("FrameWork init()");
- bottom.init();
- }
- }
-
- public class Bottom {
- private Tire tire;
-
- //现在我不自己创建了,我只拿到我想要的资源就可以了,资源怎么做的我不管
- public Bottom(Tire tire){
- this.tire = tire;
- }
-
- public void init(){
- System.out.println("Bottom init()");
- tire.init();
- }
- }
- public class Tire {
- private int size = 19;//默认为19尺寸
-
- public Tire(int size){
- this.size = size;
- }
-
- public void init(){
- System.out.println("Tire Size : " + size);
- }
- }
当我们进行修改的时候 改变用户需求:
这个时候我们只需要改变最底层的类轮胎类即可,不需要修改上层类,耦合性就降低了.代码也就好维护了.也就是对于一个类来说,他不自己去创建它依赖的类了,而是让调用者给它资源,至于怎么这个资源怎么创建的并不关心,只需拿来我依赖的资源就可以了. 也就不需要一个一个new了.
传统开发 : 最底层的代码进行修改的时候,整个调用链都要进行修改
控制反转开发 : 把控制权交给其他人,不在当前程序类里面进行new,在发生的任何改变,与我没有关系,不需要修改整个调用链的代码,实现了程序的解耦.
再次理解IOC
IOC就是一种设计思想,IOC就意味着你设计好的对象交给容器来控制,而不是传统的直接在对象的内部直接控制.
传统设计 : 直接在对象内部通过new 进行创建对象,程序主动依赖创建的对象.
IOC : 由IOC容器来控制对象的创建
谁控制谁 : IOC容器控制了对象
控制什么? 主要控制了外部资源获取(不只是对象也包括文件).
正转 : 传统应用程序由我们主动控制去直接获取依赖对象
反转 : 由容器来创建及注入依赖的对象
为什么是反转 ? 容器帮我们查找及注入依赖的对象,对象只是被动地接受依赖对象.
哪些方面反转了 ? 依赖对象的获取被反转了.
理解IOC容器
对于上面APP这个类就相当于是一个IOC容器
这个容器可以自动的对你的代码进行初始化,你只需要维护一个Configuration(可以是一个XML,可以使一段代码),不用每次初始化一辆车都要亲自去写一大堆初始化的代码
对于 Spring IOC 而言呢.以前是需要在对象的内部自己去创建,而IOC是交给spring去创建,也就是说所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转.
传统应用程序都是由我们在类的内部主动创建依赖对象,从而导致类与类之间的高耦合.
就比如 :
传统 : 应用程序是老大,想获取什么资源都是主动出击.
IOC :应用程序变为被动,被动地等待IOC容器来创建并注入它所需要的资源了.而不是对象主动去创建依赖的资源,
节省系统资源和提高程序的性能,spring IOC 是单例的,spring IOC采用的是懒汉模式,第一次调用这个类的时候我才去加载和初始化,就永远放在内存中,当其他类以后第2,3,....次用这个类的时候,不需要从新去进行类加载了,可以直接使用这个类,就不会有多个对象,不需要在用的时候再去new了.
所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中
依赖注入 就是在程序运行的时候由IOC容器动态的将我所依赖的类加入到当前类中.
就比如A对象要操作数据库,就需要一个Connection对象,有了spring就会告诉spring,我需要connection对象,至于这个connection资源怎么进行构造,什么时候构造,A不需要进行关心,在程序运行的时候,spring就会制造一个connection,然后向打针一样,注射到A当中. 完成了各个对象之间的控制.
Connection由spring注入到A当中的,所以为依赖注入
通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
DI是如何实现的呢?
Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
最终总结 Spring就是一个包含众多工具方法的IOC容器.既然是容器,Spring最核心的功能就是容器管理,也就是如何将对象存放到Spring当中, 在从Spring中获取到对象
之前是A类里面要使用B类,就需要在A对象的内部创建B,也就是A类控制了B类的生命周期(创建,销毁....),对于IOC而言,A类不需要在对象内部创建B,而是将控制权反转,交给自己的上层,让上层把资源给我,A只需告诉上层(也就是调用我的人),我需要依赖啥资源,上层就提供啥资源,A类就直接可以用他所依赖的资源了,至于这个资源怎么来的,A并不关注.此时调整参数,对A没有任何影响,因为控制权不在于A,控制权在于它的上层(调用它的人)
所谓IOC可以这么理解,就是我依赖的资源,不是由我自己来创建了,我交给Spring容器进行创建,也就相当于控制权进行反转了,所有的类都会去spring那里去登记,告诉spring,你是什么东西,你需要什么东西,然后spring就会在程序运行适当的时刻就会给你你需要的东西,然后再把你交给其他需要你的东西.所有类的创建和销毁及生命周期全部都有spring来托管/控制,而不是以前那样由引用他的对象来控制.对于具体的对象而言,以前是他控制其他对象,现在所有对象都由spring来控制.
DI就是当程序运行的时候,由IOC容器动态的将我所依赖的类加入到当前类中;
比如A类需要执行数据库操作,就需要获取到connection对象,有了spring,就会告诉spring,我需要一个connection对象,至于Connection对象怎么创建的,什么时候创建,A就不需要管,这些都会交给spring,spring会在程序运行的适当时刻创建出connection对象,然后向打针一样注入到A中,就完成了对象之间的控制,就是所谓的依赖注入
IOC 与 DI本质上就是从不同的角度说同一件事情,一个是我不自己创建我依赖的类,而交给上层去创建,然后给到当前对象,一个是由IOC容器将我所依赖的类加入到当前我的类中
区别 :IOC具体是一个思想,也可以说是一种设计模式,而对于DI来说是IOC的一个具体实现措施.
比如我今天想吃饭,对于吃饭就是一个思想,至于我去吃火锅,还是吃烧烤...这就是一个具体的实现措施.
Spring就是一个包含众多工具方法的IOC容器.既然是容器,Spring最核心的功能就是容器管理,也就是如何将对象存放到Spring当中, 在从Spring中获取到对象
参考资料 :