Spring核心 and 创建使用

Spring核心 and 创建使用

本篇内容核心:

1、Spring 是什么,如何理解Spring

2、IoC和DI是什么,有什么区别?

3、Spring最核心的功能是什么?

一、Spring的定义

​ Spring Framework(Spring 框架)通常指的是 Spring,Spring是一个开源框架,有着活跃庞大的社区,Spring支持广泛的应用场景,他可以让java企业级的应用程序开发起来更简单。

1.1什么是IoC

​ Spring是一个容器,何为容器?(指用来容纳某种物品的装置)

  • List/Map -> 数据存储容器;
  • Tomcat -> Web容器

Spring是IoC的一个容器 ,IoC(Inversion of Control)“控制反转” ,也就是说Spring是一个 “控制反转” 的容器!!!

1.1.1 理解控制反转(IoC)

举一个栗子说明:

​ 以构建一辆 车 的程序,传统的实现思路是:

​ 构建一辆车首先 需要依赖车身,车身需要依赖底盘,底盘需要依赖轮胎;程序代码如下:

image-20230703141930709


 public class CarDemo {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }

    /**
     * 汽车对象
     */
    static class Car {
        public void run() {
            // 需要依赖车身
            Framework framework = new Framework();
            framework.run();
        }
    }

    /**
     * 车身类
     */
    static class Framework {

        public void run() {
            // 需要依赖轮胎
            Bottom bottom = new Bottom();
            bottom.run();
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        public void run() {
            // 依赖轮胎
            Tire tire = new Tire();
            tire.run();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺寸
        private int size = 20;
        public void run() {
            System.out.println("轮胎尺寸:"+ size);
        }
    }
}

这上面的代码虽说可以实现这个车的构造,但是耦合性太强了,随时要依赖另一个对象,再者加上轮胎的需求尺寸是会越来越多,改变也会越来越频繁,然而上面的代码是固定尺寸,如果说需要修改尺寸,先看看修改尺寸的代码:

public class CarDemo {
    public static void main(String[] args) {
        Car car = new Car(30);
        car.run();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;
        public Car (int size) {
            // 需要依赖车身
             framework = new Framework(size);
        }
        public void run() {
            framework.run();
        }
    }

    /**
     * 车身类
     */
    static class Framework {
        public Bottom bottom;
        public Framework (int size) {
            // 需要依赖轮胎
             bottom = new Bottom(size);
        }
        public void run() {
            bottom.run();
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;
        public Bottom (int size) {
            // 依赖轮胎
             tire = new Tire(size);
        }

        public void run() {
            tire.run();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺寸
        private int size;
        public Tire(int size) {
            this.size = size;
        }
        public void run() {
            System.out.println("轮胎尺寸:"+ size);
        }
    }
}

​ 可见,一旦需要改需求那么整个程序都会受到影响,都要整体改一遍,增加工作量,增加错误率。

解决传统开发的缺陷:

​ 其中重要的思想就是 解藕 。由上面代码可知,我们在每个类里面都创建了下级类,当发生需求改变,就会整个代码改变;此时我们只需要将原来自己创建下级类,改为传递的方式(注入的方式),如果需求改变,就不需要在当前类中创建修改下级类,故下级类即使发生改变也不需要在当前类本身上面修改,这样就可以完成 “解耦”

1.1.2 控制反转式程序开发

​ 基于以上思想 “解耦” ,我们把创建子类的方式,改为注入传递的方式,具体代码如下:

public class CarDemo {
    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.run();
    }

    /**
     * 汽车对象
     */
    static class Car {
        private Framework framework;
        public Car (Framework framework) {
            this.framework = framework;
        }
        public void run() {
            framework.run();
        }
    }

    /**
     * 车身类
     */
    static class Framework {
        public Bottom bottom;
        public Framework (Bottom bottom) {
            this.bottom = bottom;
        }
        public void run() {
            bottom.run();
        }
    }

    /**
     * 底盘类
     */
    static class Bottom {
        private Tire tire;
        public Bottom (Tire tire) {
            this.tire = tire;
        }

        public void run() {
            tire.run();
        }
    }

    /**
     * 轮胎类
     */
    static class Tire {
        // 尺寸
        private int size;
        public Tire(int size) {
            this.size = size;
        }
        public void run() {
            System.out.println("轮胎尺寸:"+ size);
        }
    }
}

​ 经过了代码的调整,无论底层如何变化,中间的程序都没有发生任何改变,这样就可以完成解耦,让需求,程序更加灵活了。

对比总结:

传统代码对象创建顺序是:car->Framework->Bottom->Tire

改进之后解耦代码对象创建顺序:Tire->Bottom->Framework->car

image-20230706161805197

现在就可以发现一个规律,类的创建是相反的,经过解耦的改变,控制权发生了改变,之前的控制权是以车car为主,现在是先以轮胎Tire为主;不再是上级对象创建控制下级对象,而是下级对象把需求注入将 当前对象中 ,这样下级的控制权不再是上级控制了,即使下级类发生了改变,当前类也不会受影响的,这就是典型的“控制反正(IoC)”,也就是IoC的实现思想。

1.2 使用Spring IoC核心功能

​ Spring最核心的总结:Spring是包含了多个工具方法的IoC容器

❓❓如何理解“Spring 是一个IoC(控制反转) 容器”

​ 重点还是在 容器 二字,这个容器具有两个最基础的功能。

  • 将对象存入容器中;{存}
  • 从容器中取出对象;{取}

那么学Spring最核心的功能,就是学如何将对象存入Spring中,再从Spring中获取对象的过程

好处:

  • 将对象存储在IoC容器相当于将以后可能用到的所有工具制作好放入仓库中。
  • 需要的时候再出来拿,用完后再放回去

new对象相当于纯手工制作,每次需要工具现做,用完扔掉也不会保存,下次用还要重新做,很麻烦。这就是IoC容器和普通重新开发的区别。

📖📖最后总结:

​ Spring是一个IoC容器,对象的创建和销毁的权利都交给Spring来管理,它本身又具备了存储对象和获取对象的能力

2.1 DI的概念说明

​ DI(Dependency Injection),翻译成中文是**“依赖注入” ** ;依赖注入,就是由IoC容器在运行期间,动态的将某种依赖关系注入到对象之中。指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的“解耦”。

乍一看 DI和IoC好像说的是同一件事情,实则从不同角度来描述的同一件事情。

就好比日常生活中的内存,大家都说手机内存256G或者说128G,实则说的是手机总的外存储容量,内存是指运行内存一般是8G或者16G。

  • 广义:IoC=DI 从不同角度来描述同一件事情
  • 微观:IoC描述的是目标,DI描述的是具体可实现的思路

栗子:

目标指:晚上出去是去吃好吃的。

可实现的思路指:海底捞,火锅,烧烤…


这篇文章重点(也是面试容易问的):

1、Spring是什么,如何理解Spring

​ 答:Spring是包含众多工具方法的IoC容器。

2、IoC和DI是啥,有什么区别

​ 答:IoC是“控制反转”,DI是“依赖注入”

3、Spring最核心的功能是什么?

​ 答:具备了存储对象和获取对象的能力(存,取)。


二、Spring的创建和使用

2.1 创建一个Maven项目

image-20230706220131030

image-20230706220602010

2.2 添加Spring框架支持(依赖)

在项目pom.xml 中添加Spring框架的支持

重要的依赖:

  • spring-context (上下文)
  • spring-beans (管理对象模块)

xml配置如下:

<dependencies>
   <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
  
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
</dependencies>

image-20230706221924908

2.3 创建一个启动类(普通的类)和 main

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C0uiPMw6-1688779813804)(D:\常用文件夹\资料信息图片\Typora-image\Image\image-20230706222736675.png)]


三、将 Bean 存储到 Spring 容器中(重要)

3.1、 先创建一个 Bean

Bean 也称为 “对象” ,提到Bean就是对象的意思。

就是创建一个对象:

image-20230706223610083

3.2.将 Bean 存储到 Spring 中(将 Bean 注册到容器)

​ a)、在 Maven项目中的resources 底下创建一个 xxx(名字可以随意取).xml

里面Spring的配置文件是可以保存的,是固定格式,保存到自己能找到的地方

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    
</beans>

image-20230706224311158

​ b)、在xml中添加一个 bean,就是将刚刚创建的User对象注册到Spring中,具体操作是在 中添加。

image-20230706225112768

这里面有两个重要的属性:

  • id:是在spring中的一个身份标识,之后就是用这个身份标识完成代码
  • class:指存储对象的路径,一般是完整包名+类名

到这里就是Spring Ioc容器里面核心重要的一个“存”操作

四、获取并使用 bean对象

ApplicationContext获取上下文

1、获取Spring 上下文对象。对象都交给了Spring管理,故获取对象要从Spring中获取,那么首先需要先创建Spring上下文,再得到Spring上下文。

//1 .创建上下文需要配置spring配置信息(得到 Spring上下文)
        ApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("spring.xml");

2、使用上下文对象获得一个bean。

User user = (User) applicationContext.getBean("user");//根据 bean id来获取

这段代码没有 new 对象,是从Spring里面拿出的bean,这里就体现了Spring的价值了

3、使用 bean

user.对象的方法;

BeanFactory获取上下文

​ 这是获取 Spring 上下文的第二种方法

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));

里面的参数也是与 resources 里面的xml对应的,这是最古老的方式。

BeanFactory beanFactory1 = new ClassPathXmlApplicationContext("spring.xml");

ClassPathXmlApplicationContext 也是可以的

💀💀💀完整代码:

public class App {
    public static void main(String[] args) {
         //第二种获取Spring 上下文的方法是 BeanFactory
        BeanFactory beanFactory = new XmlBeanFactory(
                new ClassPathResource("spring.xml")
        ); //这是最古老的方式

        User user = (User) beanFactory.getBean("user");
        user.saihi();
    }
}

​ 尽然都是一样的获取上下文对象,那他们的区别又是哪里尼?

ApplicationContext vs BeanFactory

**1、**性能方面:ApplicationContext 是 一次性加载并初始化 xml 里面所有 bean 对象(在当前的 Spring 项目里面);BeanFactory 是按需求进行初始化(按照代码的调用,getBean(bean id))。故ApplicationContext 就会初始化慢,但是调用快(都初始化好了直接取出就行),BeanFactory 初始化快,但是调用慢。

ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring.xml"); // 创建并初始化所有 bean 对象

ApplicationContext 在这里就已经创建并初始化所有 bean 对象。

BeanFactory beanFactory1 = new ClassPathXmlApplicationContext("spring.xml");
User user = (User) beanFactory.getBean("user"); //真正创建 User 对象

BeanFactory 在下一步去 getBean 的时候采取创建对象。

**2、**二者的归属关系不同:ApplicationContext 输入 BeanFactory 的子类。

3、 二者的功能不同:BeanFactory 提供了基础操作 Bean 访问容器的功能: ApplicationContext 继承了BeanFactory,它除了有操作 Bean 的基础功能之外,还提供了更多的功能,如国际化的支持,事件的传播,资源访问等功能。

总结:“取”操作

image-20230706232707786

getBean()方法说明

​ getBean() 主要有三种使用的方法:

  • getBean(String s)----------- Object
  • getBean(class aClass)------------------T
  • getBean(String s, Class aclass)-----------------T

image-20230708083812368

  • 第一种是根据 bean id 获取的 Object 对象 (需要类型的强转)。对应代码:
User user = (User) beanFactory.getBean("user");
  • 第二种是根据类型获取 bean ,无需强装类型。对应代码:
User user = beanFactory.getBean(User.class);

特点:写法简单,但是如果 Spring 里面将一个对象注入多次,那么使用此方法就会导致程序异常。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XUsKGYAC-1688779813805)(D:\常用文件夹\资料信息图片\Typora-image\Image\image-20230708090518469.png)]

  • 第三种指的是 bean id ,还有bean类型 ☆☆☆☆
User user = beanFactory.getBean("user",User.class);

这种方法就解决了上面两种方法的缺点,不用强转类型,也不用担心一个对象在 Spring 里面注入多次而报错,大多数使用的就是第三种方法。


五、Spring创建使用总结

image-20230708092224687


  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鸢也

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

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

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

打赏作者

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

抵扣说明:

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

余额充值