认识Spring

1.1 Spring的历程

早期的 Java EE 使用 EJB 为核心的开发方式,但是这种开发方式在实际开发环境中存在诸多问题: 使用复杂, 代码臃肿, 移植性差等.
于是"Spring 之父" Rod Johnson 在其畅销书《Expert One-on-One J2EE Design and Development》中使用一个3万行代码的附件,展示在不使用EJB的情况下创建一个拓展性强, 高质量的 Java 应用程序, 随着这本著作的流行, Rod Johnson 把这份源码开源, 并把这个新框架命名为: “Spring”, 含义为: Spring 像一缕春风一样,扫平传统 J2EE 的寒冬.于是在2004年3月24日发布了 1.0 正式版本.

1.2 Spring的含义

广义的 Spring

广义上的Spring指的是以Spring Framework 为核心的 Spring 技术栈.
衍生的相关技术有: Spring Framework、Spring MVC、SpringBoot、Spring Cloud、Spring Data、Spring Security 等

狭义的 Spring

狭义的Spring: Spring Framework , 通常被称为Spring 框架
Spring 有两个核心部分: AOP 和 Ioc
AOP (Aspect Oriented Programming) 译为"面向切面编程" , 利用AOP 把为业务服务的但是不属于业务部分的逻辑封装,增加代码的复用性, 降低模块之间的耦合度,除此之外, AOP 还可以解决日志, 事物, 权限等系统层面的问题.
IOC (Inverse of Control ) 译为"控制反转", 指把创建对象过程交给 Spring 进行管理
用一句话概括Spring: Spring是包含众多工具方法的IoC容器.

什么是容器?

我们回忆之前学习的知识, 在Java中的List/Map是数据存储容器, 在Java Web中 的Tomcat 是 Web容器. 那么对应的Spring 就是 存储 IoC的容器.

什么是Ioc?

下面利用两种不同的方式构建Car对象来认识其区别.

假如你现在收到一个项目: 客户需要定制化的选择的新车的组件及其配件. 那么对于一个Car对象是由许多组件构成, 这些组件又由更多小组件组成,所以下面的就简化的提供一个依赖关系.

传统的程序开发:
传统开发采当需要下层对象时在当前类中 引入该对象 即可, 这样就会衍生出许多问题,先上代码

package Old;

public class CarExample {

    public static void main(String[] args) {
        Car car = new Car(20);
        car.init();
    }

    /**
     * 汽⻋对象
     */
    static class Car {
        private Framework framework;

        public Car(int size) {
            this.framework = new Framework(size);
        }

        public void init() {
            // 依赖⻋身
            framework.init();
        }
    }

    /**
     * ⻋身类
     */
    static class Framework {
        private Bottom bottom;

        public Framework(int size) {
            this.bottom = new Bottom(size);
        }

        public void init() {
            // 依赖底盘
            bottom.init();
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;

        public Bottom(int size) {
            this.tire = new Tire(size);
        }

        public void init() {
            // 依赖轮胎
            tire.init();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺⼨
        private int size = 30;

        public Tire(int size) {
            this.size = size;
        }

        public void init() {
            System.out.println("轮胎尺⼨:" + size);
        }
    }

}

当前需求只是客制化轮胎尺寸,但是后期有了更多的需求,那么代码的改动就会很大,这就是代码的耦合度很高,那么如何降低耦合度呢? 那么就可以把控制权交给上级类,由上级类实现下级类的初始化.
控制反转式程序开发:
通过控制反转开发的手段,就可以实现模块之间的解耦,假如需求增加底盘的高度,车身的颜色,车身的材质,实现代码如下:

package New;


class CarExample {
    public static void main(String[] args) {
        // 自定义轮胎尺寸
        Tire tire = new Tire();
        tire.setSize(32);

        // 自定义底盘高度
        Bottom bottom = new Bottom(tire);
        bottom.setHeight(20);

        // 自定义车身的颜色和材质
        Framework framework = new Framework(bottom);
        framework.setColor("Green");
        framework.setMaterial("钛合金");

        // 最后将这些组件组装好
        Car car = new Car(framework);
    }

    /**
     * 汽⻋对象
     */
    static class Car {
        private Framework framework;

        public Car(Framework framework) {
            this.framework = framework;
        }

        public void init() {
            // 依赖⻋身
            framework.init();
        }
    }

    /**
     * ⻋身类
     */
    static class Framework {
        private Bottom bottom;
        private String color = "Red";
        private String material = "镀锌薄钢板";

        public void setColor(String color) {
            this.color = color;
        }

        public void setMaterial(String material) {
            this.material = material;
        }

        public Framework(Bottom bottom) {
            this.bottom = bottom;
        }

        public void init() {
            // 依赖底盘
            bottom.init();
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;
        private int height = 10;

        public Bottom(Tire tire) {
            this.tire = tire;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public void init() {
            // 依赖轮胎
            tire.init();
            System.out.println("底盘高度: " + height);
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺⼨
        private int size = 30;

        public Tire() {

        }

        public void setSize(int size) {
            this.size = size;
        }

        public void init() {
            System.out.println("轮胎尺⼨:" + size);
        }
    }
}

因为通过传递的方式(也就是注入的方式), 我们不需要在当前类中创建下级类,即使下级类改变或者增加属性都不会影响当前类,当前类需要什么就通过set()方法设置好然后交付给上级类,从而降低类之间的耦合度.

对比总结:
在传统开发中采用的,Car对象控制并创建了Framework, Framework对象控制并创建了Bottom,依次向下,而修改后的代码的控制权发生了反转, 不再由是上级对象创建和控制了,而是把下级对象注入到当前对象中,于是下级对象内部改变不会影响到当前类,这就是典型的控制反转,也就是Ioc的实现思想.

再次理解Ioc

通过上述开发方式的转化,实现控制权的翻转,这是Ioc的一个特点,那么如何理解"Spring 是一个Ioc容器",那么对于容器所具备的特性;

  • 把物品存储到容器中
  • 把物品从容器从取出来

那么对应到Ioc容器中就是关于对象的存取操作: 把对象存储到Spring中,把对象从Spring中取出.

Spring是包含众多工具方法的容器,那么把对象存储到Ioc容器中就可以对容器中的工具"随用随取, 用完放回".不必在需要某个工具(对象)时才去创建, 和传统开发需要时创建有着很大区别.

对于传统开发中需要某个对象时就使用 new 去创建(二者之间的关系称为依赖, 比如底盘依赖于轮胎),不妨称 new 对象的类为"调用者", 被 new 的对象称为"被调用者" ,那么调用者掌握着被调用者的控制器,而在Spring中,由于把对象都’存储’到IoC容器中,调用方变成被动的去请求IoC容器创建对象,此时就发生明显的控制反转.

DI概述

DI (Dependency Injection 依赖注入),依赖注入不是一个设计思想,而是一个具体的实现技术,指的是在IoC容器运行期间动态的把依赖对象注入到当前对象中的技术就是DI.
例如 上面的Bottom(底盘类) 依赖 Tire(轮胎类) , 把Tire对象注入到Botom对象的操作就是DI(依赖注入)

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;
        private int height = 10;

        public Bottom(Tire tire) {
            this.tire = tire;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public void init() {
            // 依赖轮胎
            tire.init();
            System.out.println("底盘高度: " + height);
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺⼨
        private int size = 30;

        public Tire() {

        }

        public void setSize(int size) {
            this.size = size;
        }

        public void init() {
            System.out.println("轮胎尺⼨:" + size);
        }
    }
    public static void main(String[] args) {

        Tire tire = new Tire();
        tire.setSize(32);

        // 把构造好的tire对象注入bottom对象的技术就是依赖注入.
        Bottom bottom = new Bottom(tire);
        bottom.setHeight(20);

    }

IoC 和 DI 的区别

共同点: 二者都是从不同的维度, 描述同一件事(如何实现程序的解耦, 达到控制权的反转)
不同点: IoC是实现的思想, DI是实现IoC思想的一个具体手段

比如今天的完满的完成了今天的任务,我决定要"奖励自己", 那么奖励自己是一个思想并没有具体的实现; 对应的DI就是如何具体的实现,如奖励自己玩游戏,吃KFC等.

1.3 Spring的特点

  1. 方便解耦, 简化开发

Spring是一个大容器,可以把对象的创建,依赖关系的维护等交付给Spring管理

  1. 更加简易的集成各种优秀框架

Spring可以支持对各种框架(Hibernate,MyBaits等)的直接支持.

  1. 降低 Java EE API 的使用难度

Spring对Java EE 中一些难用的API(JDBC,远程调用等)都提供了封装,上手难度大大降低

  1. 方便程序的调试

Spring 支持 JUnit4, 可以通过注解方便地测试 Spring 程序

  1. AOP 编程的支持

Spring 提供面向切面编程, 可以方便地实现对程序进行权限拦截和运行监控等功能

  1. 声明式事务的支持

只需要通过配置就可以完成对事务的管理,而无须手动编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zzt.opkk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值