Spring----核心设计思想

一)Servlet使用和Springboot使用的区别

一:创建一个项目:

一)Servlet创建项目流程复杂

1)创建maven项目

2)去中央仓库去查找Servlet对应的版本和引用信息(特别麻烦),还要搞定Tomact和Servlet版本是否一致,添加外部jar包,进行搜索,之前需要先进行查询项目版本需要匹配的外部jar包,放到pom.xml就行了

3)点击maven导入框架按钮,创建JAVA源代码的项目目录

二:SpringBoot项目创建非常简单:

二:编写代码来说:

一:对于咱们的Servlet编写代码来说:路由配置不方便

二:针对SpringBoot项目来说:

 SpringBoot会自动把返回类型设置成JSON格式的数据,也就是会自动设置ContentType

三:运行项目:

一:运行Servlet项目:

二:运行SpringBoot项目:

1)SpringBoot会去帮你自动启用一个8080的端口号,然后你的SpringBoot的版本号会有一个与之相匹配的Tomact的版本所以说Tomact的版本不需要担心会去自动适配Tomact版本

2)SpringBoot会自动根据你返回的类型来去帮你自动地去设置返回的格式和编码,自动会帮我们进行转换

四:对于咱们的发布项目来说:

五:返回的数据:

SpringBoot相比于Servlet优点小结:

1)添加外部jar包更方便,不容易出错,因为版本问题不需要关注

2)调试项目更加方便,无需配置Tomact

3)发布项目更加方便,无需配置Tomact

4)添加路由更加方便,无需每一个访问地址都添加一个类

二)什么是Spring?什么是IOC?什么是容器?

容器是用来容纳某种物品的基本装置,Java 中也有一些容器,比如 List,Map,Set 等这些集合,是属于数据储存的容器,它把我们常用的操作都封装到集合中了,只需要知道集合为我们提供的方法就可以使用各种集合了;还有 Tomcat 是属于 Web 容器,同理 Spring 是就一个 IoC 容器,它包含了许多的工具和方法

Spring是Spring Framework,他是一个开源框架,有着庞大而活跃的社区,是可以支持广泛的应用场景,可以让Java企业级的应用程序开发起来变得更简单,是包含了众多工具方法的IOC容器;

解释一下为什么Tomact是一个Web容器呢?

Tomact是用来运行web的项目,因此它是一个Web容器,你如果是有一个Web项目想要进行运行,那么必须要将项目打包成war包并部署到Toamct的webapps目录下面才可以进行运行

此时的构造方法已经从原来的无参的构造方法变成了有参的构造方法

因为此时很有可能在我们的实际业务中很有可能是B的构造方法写错了,忘记加参数了,于是就又从后面补充了一些参数,那么此时A的调用就会发生报错;

于是我们就可以将对象传递而非new对象的方式来进行解决,即使需要加更多的参数,都是不需要修改A类的

1)从上面的内容我们可以看出IOC和DI虽然定义不同,但是他们所做的事情都是一样的,都是来实现对象解耦合的,而两者又有些不同IOC是一种设计思想而DI是一种具体的实现技术

2)比如说我今天学习累了,想去吃顿好的,就是IOC,但是我具体想要吃什么,是海鲜还是海底捞,就叫做DI;

3)IOC和DI都是Spring框架里面的重要概念,它们都是用来实现对象解耦合的,IOC控制反转是一种设计思想,而DI依赖注入是一种具体实现手段;

1)IOC就是控制反转的意思,这是一种思想,控制权反转,在JAVA的常规的代码中,对象的生命周期是由程序员自己来进行控制的,而控制反转就是把对象的生命周期不交给当前代码片段来控制,而是由Spring IOC容器来进行控制

2)都知道想要造一辆小汽车,需要有车身,而车身需要底座和轮胎,最传统的思想就是造车的时候需要造车身,于是就new出了一个车身,而车身需要底座,于是又new了一个底座,同理底座需要轮胎,于是又不得不new出一个轮胎

1)既然想要造出一辆车,那么一定是要有一个car类,但是车是依赖于车身的,所以要有一个车身类Framework,但是车身又是要依赖于底盘的,所以我们还要有一个底盘类,Bottom,但是底盘是要依赖于Tire(轮胎类),就是说我现在想造一辆车,发现没有车身,然后在车里面再造车身;造着车身的过程中,发现没有底盘,然后在车身里面造底盘,底盘在进行构造的过程中,发现没有轮子,然后再从底盘里面去造轮子;

2)类创建的顺序是从上到下进行构造:车-->车身-->底盘-->轮子,需要用到哪一个类,就去创建这个类

class Car{
  public void start()
  {
      FrameWork frameWork=new FrameWork();
      frameWork.start();
  }
}
class FrameWork{
    public void start()
    {
        Bottom bottom=new Bottom();
        bottom.start();
    }
}
class Bottom{
    public void start(){
       Tire tire=new Tire();
       tire.start();
    }
}
class Tire{
    public static final int size=90;
    public void start(){
        System.out.println("现在车已经造好了,况且车的尺寸是"+size);
    }
}
class HelloWorld{
    public static void main(String[] args) {
        Car car=new Car();
        car.start();
    }
}

但是现在他出现了一种问题,只能创造一种形态的车(固定尺寸),因为人们的需求肯定是在不断变化的,一种轮胎是不可能满足不同人群对于尺寸的要求;

4)我们此时就要给轮胎传入一个参数size,让轮胎创造出不同尺寸的车,但是此时我们发现,想要给轮胎的start方法传入参数之后,因为底盘是依赖于轮胎的,底盘的控制权是在轮胎里面的,这时的上一个创建底盘类的时候在接口里面就要传入一个size参数,不然代码会报错(从某一个角度来说,不同的轮子需要不同的车身,底盘;

5)改造轮胎类---->改造底盘类----->改造车身类----->改造车类(从下向上传参),哪一个类用到这个类直接就在这个类里面创建这个类所依赖的对象

class Car{
    public void start(int size)
    {
        FrameWork frameWork=new FrameWork();
        frameWork.start(size);
    }
}
class FrameWork{
    public void start(int size)
    {
        Bottom bottom=new Bottom();
        bottom.start(size);
    }
}
class Bottom{
    public void start(int size){
        Tire tire=new Tire();
        tire.start(size);
    }
}
class Tire{
    //public static final int size=90;
    public void start(int size){
        System.out.println("现在车已经造好了,况且车的尺寸是"+size);
    }
}
class HelloWorld{
    public static void main(String[] args) {
        Car car=new Car();
        car.start(30);
//我们就可以在这里面根据传入的轮胎的大小的不同来进行创建不同的车
    }
}

那么如何进行只修改一个类?不影响上面的调用链所有类呢?

1)把所有个性化的需求都给外包出去,把不同的组件分给不同的厂子去做,我们尝试不在每一个类中创建下级类,如果创建下级类就会出现当下级类发生改变操作的时候,自身也要发生改变,发生修改;

2)此时我们只需要将原来由自己创建的下级类改为传递的方式,以后是注入的方式,此时我们就不需要进行创建下级类了,即使下级类发生了变化(新增参数或者减少参数),当前类就不需要进行修改任何代码,也就实现了解耦

1)控制反转性程序开发,现在不是自己造了,给别人做,把控制权和做产品的过程交给了工厂,我最终可以拿到的只是一个产品,而不需要自己造产品。控制权发生反转,把各种组件交给其他的不同的公司;

2)在每一个类里面,在这个类里面不造依赖类,只是用这个类(通过构造方法来进行传递),只需要把自己用到的类给注入进来就可以了,减少依赖关系,就算这个所依赖的类发生了修改,那么上面的调用链上面的类是不需要进行修改的,我们不需要关注这个依赖类是怎么实现的;

3)先要创建最底层的类:

class Car{
    FrameWork frameWork;
    public Car(FrameWork frameWork)//直接从固定的容器里面拿
    {
        this.frameWork=frameWork;
    }
    public void start(){
         frameWork.start();
    }
}
class FrameWork{
    Bottom bottom;
    public FrameWork(Bottom bottom)
    {
        this.bottom=bottom;//注入的底盘是多大尺寸,车身就用多大尺寸
    }
    public void start(){
      bottom.start();
    }
}
class Bottom{
    Tire tire;
    public Bottom(Tire tire)
    {
        this.tire=tire;//注入的轮胎是多大尺寸,底盘就用多大尺寸
    }
    public void start()
    {
         tire.start();
    }
}
class Tire{
    private int size;
    //在进行构建这个类的时候,进行下层依赖的注入
    public Tire(int size)//进行下单
    {
        this.size=size;
    }
    public void start(){
        System.out.println("现在车已经创建好了,尺寸是"+size);
    }
}
class HelloWorld {
    public static void main(String[] args) {
//从底层向上进行创建,这就实现了控制反转
        Tire tire=new Tire(40);
        Bottom bottom=new Bottom(tire);
        FrameWork frameWork=new FrameWork(bottom);
        Car car=new Car(frameWork);
        car.start();
    }
}

这样我们就可以通过改变轮胎里面的尺寸来构建不同尺寸的车了,当我们想要引入不同颜色的时候,只需要进行修改轮胎类就行了,而底盘类,车身类全部不需要进行修改,当我们的需求发生了颠覆性的变化,此时我们发现整个调用链上的类的代码不发生任何变化,底层的类是需要注入到上层的调用类里面的;

class Car{
    FrameWork frameWork;
    public Car(FrameWork frameWork)
    {
        this.frameWork=frameWork;
    }
    public void start(){
        frameWork.start();
    }
}
class FrameWork{
    Bottom bottom;
    public FrameWork(Bottom bottom)
    {
        this.bottom=bottom;//注入的底盘是多大尺寸,车身就用多大尺寸
    }
    public void start(){
        bottom.start();
    }
}
class Bottom{
    Tire tire;
    public Bottom(Tire tire)
    {
        this.tire=tire;//注入的轮胎是多大尺寸,底盘就用多大尺寸
    }
    public void start()
    {
        tire.start();
    }
}
class Tire{
    private int size;
    private String color;
    //在进行构建这个类的时候,进行下层依赖的注入
    public Tire(int size,String color)//进行下单
    {
        this.size=size;
        this.color=color;
    }
    public void start(){
        System.out.println("现在车已经创建好了,尺寸是"+size+"颜色是"+color);
    }
}
class HelloWorld {
    public static void main(String[] args) {
//从底层向上进行创建,这就实现了控制反转
        Tire tire=new Tire(40,"红色");//只需要改变这个属性就行了
        Bottom bottom=new Bottom(tire);
        FrameWork frameWork=new FrameWork(bottom);
        Car car=new Car(frameWork);
        car.start();
    }
}

1)IOC实现思想:两次创建类的顺序都发生了改变,程序的实现代码,类的创建顺序是反的,传统代码是Car类控制并创建了FrameWork类,FrameWork类创建并创建了Bottom类,从上向下

2)但是改进之后不再由上层对象控制下层对象了,而是把下层对象注入到上层对象了,下层的控制权不再由上层类控制了,这样即使下层类发生任何改变,上层类都是不会受到影响的,这就是典型的控制反转,直接从Spring中取;

IOC:对象的生命周期交给IOC框架去维护,而不需要程序员进行关注了,用到的时候不需要new,只需要拿过来用就可以了,不关心程序具体生命周期创建的细节,比如说在你进行构建轮胎类的时候,你是依赖于底盘的,但是你是通过构造方法来进行注入的,Tire不是FrameWork来进行构建的

 三)控制反转IOC的基本实现(优点和特点)

1)当底层调用类发生改变之后(不管有几个参数),只需要在最底层的类进行修改就行了,IOC模式的整个调用链上的代码是不需要进行修改的,实现了类和引用类的解耦合,但传统的开发方式是不可以的

2)与依赖类的关系发生改变:之前如果我们如果需要使用依赖类,我们就需要自己进行创建并进行管理类的生命周期,IOC是不用程序员自己进行管理类的生命周期的,我不管依赖类是什么时候进行创建的,什么时候进行销毁的,在需要的时候,只需要拿过来用就可以了,控制权由自己交给了他人,控制权发生了反转;

Spring,就相当于是咱们上面的那一个外包公司

既然Spring是一个集成多个工具方法的(控制反转)IOC容器,重点还是体现在容器上面,那么它就具有两个最完备最核心的功能:

1)将对象Bean入到容器里面

2)从容器中出Bean对象

3)咱们学习Spring最核心的功能,就是学如何将对象存入到Spring中,再从Spring中获取对象的过程,说的就是将对象的创建和销毁,对象的生命周期都交给Spring来进行管理了,它本身又具备了存储对象和获取对象的能力(控制权的一个反转);

1)将对象放到容器里面的好处:将对象存储到IOC容器里面相当于将以后可能会用到的所有工具制作好放到仓库里面,需要的时候直接取就可以了,用完之后再次将它放回到仓库里面

2)但是我们在进行new对象的方式就相当于是,每一次需要工具了,才会现做,用完之后扔掉了也不会进行保存,下次在用的时候还要重新去做,这就是IOC容器和普通程序进行开发的区别;

将对象存储到IOC容器相当于是说将我们所有可能用到的工具全部放到仓库,当时用的时候直接取出来即可,用完以后直接归还到仓库,下一次现取现用,用完以后归还给仓库

而 new 对象的方式相当于我们每次需要用工具的时候现场制作,制作完了扔掉,下次需要的时候重新做

DI:它是Dependency Injection的缩写,翻译成中文是依赖注入的意思

1)所谓的依赖注入(是一个具体的实现手段或技术),是在IOC容器启动的时候,是动态的将某种依赖关系注入到一个类里面,所以依赖注入和控制反转是从不同的角度的来描述一件事情,就是指依赖IOC容器,利用依赖关系注入的方式,来实现对象之间的解耦;

2)进一步来说,是在进行创建当前类的时候,动态地将当前类的依赖对象注入(注册)进来的过程就叫做DI,这就叫做依赖注入; 

3)IOC就是把创建对象销毁对象的权限交给他人了,自己不进行管理了,IOC是控制反转,是一种实现思想;DI是控制反转的一个实现手段;IOC有很多种实现,但是DI只是其中的一种;

依赖:A对象里面要创建B对象,说明A依赖B

注入:A对象里面现在不需要创建B对象了,直接把B对象拿过来了直接用这就叫做注入

依赖注入避免new

所谓依赖注⼊,就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中,在pom.xml有一个依赖项,就是用来导入外部的资源,而这里的依赖注入,导入的不是外部的资源,而是对象;当某个 Java 实例需要另一个 Java 实例时,创建被调用者的工作不是由调用者实现,而是由 Spring 容器来完成,然后注入调用者,因此称为依赖注入

区别:IOC是一个目标也是一种控制反转指导思想,而思想和目标只是一种指导原则,最终还是要有可行的落地方案,而DI就属于具体的实现,依赖注入

IOC:心情比较好,要去吃一段好的-------思想

DI:吃麻辣烫,海底捞?--------具体实现

乐观锁:认为一般情况下不会出现锁竞争的情况,是一种思想,只有在发生数据修改的时候才会进行加锁操作,但是没有说具体是怎么实现

CAS:是一种实现机制和手段,修改并比较;

依赖注入和依赖查找的区别就是依赖注入是将依赖关系委托给容器,由容器本身来进行管理对象之间的依赖关系,容器外部是不关心这种依赖关系的,需要的时候有容器来进行判断提供什么,但是依赖查找是由对象自己本身来查找她所依赖的对象,容器只是区负责管理对象的生命周期,也就是说此时需要容器外部自己确定要容器提供哪种依赖关系;两者之间是主动和被动的区别

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值