Spring基础知识讲解

2023-11-04

Spring是什么?

Spring指的是Spring Framework(Spring框架),它是一个开源框架,有非常活跃和庞大的社区支持,Spring支持广泛的应用场景,可以让Java企业级开发更简单。Spring是包含众多工具方法的IoC容器,Spring最核心的功能就是容器管理

IoC容器与DI

我们需要理解一下Spring是包含众多工具方法的IoC容器这句话,什么是IoC呢?IoC = Inversion of Control 翻译成中文就是控制反转,我们通过一个例子来解释一下这个名词。

构建⼀辆⻋(Car Class),然⽽⻋需要依赖⻋身(FrameWork Class),⽽⻋身需要依赖底盘(BottomClass),⽽底盘需要依赖轮胎(Tire Class),此时我们传统开发的方法来完成这个需求:


class Car {

    private Framework framework;

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

    public void init() {
        System.out.println("构造Car");
        framework.init();
    }
}


class Framework {

    private Bottom bottom;

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

    public void init() {
        System.out.println("构造Framework");
        bottom.init();
    }

}

class Bottom {
    private Tire tire;

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

    public void init() {
        System.out.println("构造Bottom");
        tire.init();
    }
}

class Tire {
    int size = 15;

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

    public void init() {
        System.out.println("车轮子 = "  + size);
    }
}

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

在这里插入图片描述
运行代码完成了需求,但是当我们需要增加一个属性的时候会非常困难,比如我们增加一个轮子的颜色属性。
在这里插入图片描述
可以看到,当我们更改了底层的代码,整个调用链上的所有代码都需要修改,如何解决这个问题呢?我们可以模拟一下IoC容器,将传统的new对象的方式改为注入传递的方式。

class Car {

    private Framework framework;

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

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

    public void init() {
        System.out.println("构造Car");
        framework.init();
    }
}


class Framework {

    private Bottom bottom;

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

    public void init() {
        System.out.println("构造Framework");
        bottom.init();
    }

}

class Bottom {
    private Tire tire;

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

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

    public void init() {
        System.out.println("构造Bottom");
        tire.init();
    }
}

class Tire {
    int size = 15;
    String color;

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

    public void init() {
        System.out.println("车轮子 = "  + size);
    }
}

public class Test {

    private Car car;
    private Framework framework;
    private Bottom bottom;
    private Tire tire;

    public Test() {
        this.tire = new Tire(20,"blue");
        this.bottom = new Bottom(this.tire);
        this.framework = new Framework(this.bottom);
        this.car = new Car(this.framework);
    }

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

经过调整,现在更改底层代码是不会影响整个调用链的,这样完成对代码的解耦。我们发现,传统的代码是上层代码依赖下层代码,由上级对象创建下级对象,而更改后的代码,是把下层代码注入到上层代码,这样下级代码的控制权不在由上级控制,自然下级代码更改不会影响上级代码了,这就是所谓的控制权反转,也是IoC容器的思想。

所以Spring 是包含了多个⼯具⽅法的 IoC 容器,可以理解为Spring是一个控制反转容器,既然是容器那么就可以存东西和取东西。所以对象的创建和销毁的权利都交给 Spring 来管理了,它本身⼜具备了存储对象和获取对象的能⼒。也就是,创建类的时候将类存到Spring容器中,在创建对象时不需要new了,直接去Spring中取对象。所以学习Spring最核心的功能就是如何将对象存到Spring中,再从Spring中获取对象的过程。

DI与IoC的区别

上面我们知道了IoC是控制权反转的一种思想,那么DI又是什么呢?DIDependency Injection 的缩写,翻译成中文是依赖注入。他与IoC是从不同角度描述的同一件事,IoC是一种思想,而思想执行需要方法,IoC就是思想,DI就是具体得到实现方式。

Spring项目的创建

配置maven国内源

在这里插入图片描述
在设置中勾选setters.xml配置文章和本次仓库文件。
在这里插入图片描述
在settings.xml中配置国内源

<mirror>
        <id>alimaven</id>
        <name>aliyun maven</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        <mirrorOf>central</mirrorOf>        
</mirror>

在这里插入图片描述
删除本地所有的jar包,重新下载
在这里插入图片描述

创建Spring项目

首先创建一个maven项目
在这里插入图片描述
添加Spring依赖

<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>

在这里插入图片描述

有关Bean的操作

存储Bean

创建一个启动类
在这里插入图片描述

存储Bean对象分为两个步骤:
1、创建一个Bean对象。
2、将创建的Bean对象注册到Spring容器中。

创建一个Bean对象,就是一个普通的类对象。
在这里插入图片描述
添加Spring配置文件spring-config.xml

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <bean id="student" class="com.java.demo.model.Student"></bean>
</beans>

使用Bean

使用Bean对象,分为三步:
1、得到Spring上下文对象,因为对象都交给了Spring管理了,所以对象需要从Spring中获取。
2、通过Spring上下文,获取某一个指定的Bean对象。
3、使用Bean对象。

使用 ApplicationContext获取上下文对象,使用getBean()方法获取Bean对象。

在这里插入图片描述
此时运行代码我们看到打印出了Student对象的信息。
在这里插入图片描述

ApplicationContext和BeanFactory的区别

BeanFactoryApplicationContext的作用一样都是获取上下文对象的,他俩的区别可以从两个方面说:

1、从继承关系来说,ApplicationContextBeanFactory的子类,他有更多的功能,比如对国际化的支持、资源访问支持、以及事件传播等方面的支持。
2、从性能放面来说:ApplicationContext是一次性加载所有Bean对象,BeanFactory是懒加载,只加载使用的Bean对象。

getBean()的三种使用方法

在这里插入图片描述
使用图中的三种方法都可以获取到Bean对象,注意如果有多个相同的Bean对象,使用类名获取Bean对象的方法就会报错。

更简单的存储和获取对象

我们发现使用框架写代码竟然比传统开发的代码还要复杂,有没有方法使存储Bean对象和获取Bean对象的过程便简单呢?

我们可以通过两个方法实现更简单的存储Bean:
1、使用类注解的方法实现Bean对象的存储。
2、使用方法注解的方法实现Bean对象的存储。

首先同样要添加Spring配置文件spring-config.xml,这次添加的配置文件有所不同。
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <content:component-scan base-package="com.java.demo"></content:component-scan>
</beans>

类注解

五大类注解分别是:
1、@Controller 控制器,检测数据的合法性
2、@Service 服务层,进行业务组装
3、@Repository 数据持久层,实际业务的处理
4、@Component 组件 工具类层
5、@Configuration配置层 进行配置

使用这些类注解都可以将类储存到IoC容器中,那为什么要分这么多注解呢?原因就是让程序员看到类注解之后,就可以了解到当前类的用途

在这里插入图片描述
此时会有一个问题,我们在配置文件中并没有配置Bean对象,也就是说没有设置Bean对象在IoC中id,那我们如何获取Bean对象呢?

使用类注解存储Bean的命名规则如下:
1、当类的命名为默认大驼峰(首字母大写第二个字母小写),可以使用类名首字母小写获取到Bean对象。
2、如果不满足上面的大驼峰的情况,直接使用类名就可以获取到Bean对象。

方法注解

除了使用类注解的方法进行存储,还可以使用方法注解的方式。
在这里插入图片描述
@Bean的默认命名方式为方法名,我们还可以进行重命名。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
还可以指定多个名称
在这里插入图片描述

@Bean获取时的一些注意事项:
1、如果多个Bean使用相同的名称,执行程序不会报错,只会将第一个Bean对象存储到容器中,后面的会自动忽略。
2、如果对@Bean进行了重命名,那么默认使用方法名获取Bean的方法将会失效。

获取Bean对象的简单方法——依赖注入

之前我们获取Bean对象的方法称为依赖查找,很麻烦,我们还有更简单的方法依赖注入。

我们有三种方式进行对象注入:
1、属性注入
2、构造方法注入
3、Setter注入

属性注入:
在这里插入图片描述

使用属性注入的优缺点:
优点:代码简单
缺点:无法注入final修饰的变量,可能违反单一性设计原则

构造方法注入:
在这里插入图片描述

使用属性注入的优缺点:
优点:可以注入一个final修饰的变量,注入的对象不会被修改,构造方法可以保证注入对象完全初始化,构造方法注入通用性更好。
缺点:代码更加复杂,无法解决循环依赖的问题。

setter方法注入:
在这里插入图片描述

使用属性注入的优缺点:
优点:Setter注入更符合单一设计原则
缺点:无法注入final修饰的变量,Setter注入的对象可以被修改。

除了使用@Autowired注解进行注入,还可以使@Resource进行注入。
在这里插入图片描述

@Autowired和@Resource的区别

1、@Autowired来自于Spring,而@Resource来自于JDK
2、使用时可以设置的参数不同,@Resource有更多的参数
3、@Resource只能用于Setter注入和属性注入,不能用于构造函数。

关于设置的参数我们举个例子来说明解释一下:
我们使用@Bean注入两个返回相同对象类型的Bean:
在这里插入图片描述
此时使用@Autowired@Resource获取Bean对象会报错
在这里插入图片描述
报错原因是使用@Autowried进行依赖注入的过程是先根据getType获取对象,如果只获取到一个,那么会直接注入到属性上去,如果有多个会使用getName进行匹配。
在这里插入图片描述
所以此处我们有三种方法解决Bug
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Bean的作用域和生命周期

作用域

我们通过一个例子来观察一下Bean的作用域:现在有一个Student类通过@Bean的方式进行了注入,此时有两个类都需要使用这个Bean对象,但是其中一个类需要进行修改Bean对象中的属性,一个不需要任何改动,此时会发生什么呢?
在这里插入图片描述
我们的预期是,公共的Bean对象在各自的类中可以被修改,但是不能影响其他类,但是结果不尽人意。
在这里插入图片描述
造成这个结果的原因就是Bean的作用域,Bean在默认的情况下是单例的状态,也就是所有人都是同一个对象,自然我们在一个类中进行修改,另一个类中的对象也会更改。解决这个问题的方式就是改变Bean对象的作用域,Bean的作用域有哪些呢?

Bean的作用域有6种:

  1. singleton:单例作⽤域 (默认)
  2. prototype:原型作⽤域(多例作⽤域)
  3. request:请求作⽤域
  4. session:回话作⽤域 一个会话共享一个Bean
  5. application:全局作⽤域 一个Context容器共享一个作用域
  6. websocket:HTTP WebSocket 作⽤域

前两个作用域适用于普通Spring项目,后四个都是Spring MVC的项目。

设置作用域

我们可以使用@Scope来设置作用域
在这里插入图片描述
再次运行项目此时完成我们的需求。
在这里插入图片描述

生命周期

Bean的执行流程

1、启动Spring容器
2、实例化Bean
3、Bean注册到Spring中
4、将Bean装配到需要的类中

Bean的生命周期

1、实例化Bean(为Bean分配内存空间)
2、设置属性(Bean注入和装配)
3、Bean初始化
3.1、实现了各种Aware通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法
3.2、执行 BeanPostProcessor初始化前置方法
3.3、执行@PostConstruct初始化方法,依赖注入操作后被执行
3.4、执行自己指定的init-method方法
3.5、执行BeanPostProcessor初始化后置方法
4、使用Bean
5、销毁Bean

Bean的初始化比较复杂简单总结就是:

1、执行各种通知
2、初始化的前置方法
3、初始化方法
4、初始化的后置方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring基础知识讲解 的相关文章

随机推荐

  • vue其他之“命名规则”

    骆驼式命名法在许多新的函数库和Microsoft Windows这样的环境中使用得相当多 另一方面 下划线法是c出现后开始流行起来的 在许多旧的程序和UNIX这样的环境中 它的使用非常普遍 驼峰式命名法 由一个或多个单词连结在一起 而构成的
  • 攻防世界(adworld) WEB Exercise area(练习区)10题解题思路

    攻防世界 https adworld xctf org cn view source 点右键看源代码被禁止了 要么F12 要么去其他工具中请求就可以了 robots 机器人协议 是规定了爬虫哪些页面可以爬 哪些不可以 robots txt
  • LeetCode每日一题(2444. Count Subarrays With Fixed Bounds)

    You are given an integer array nums and two integers minK and maxK A fixed bound subarray of nums is a subarray that sat
  • [OpenGL] CentOS7 安装 mesa

    CentOS 7安装 mesa How to install mesa on centos 7 1 下载原文件 下载连接 mesa 11 1 3 tar gz freeglut 3 0 0 tar gz libdrm 2 4 66 tar
  • PCB中焊盘和字体整体变透明原因

    之前画PCB时候发现怎么PCB元器件颜色看着很透明 想想看自己也没干什么 怎么变透明了 透明图如下所示 从上图来看是不是焊盘和字体都透明一样 后来发现原来是之前自己看3D时候把颜色改了 切换回2D时候设置为2D透明模式了 如图所示 把这个2
  • 2023年大厂裁员严重,软件测试行业真的饱和了吗?

    这短时间以来后台有很多小伙伴说找工作难 并且说软件测试行业饱和了 竟然登上了热榜 那么我今天带大家看看真实的市场行情 往下看 这个是公司联合某厂的HR招聘真实情况 很明显 软件测试 投简历竟然高达9999 沟通才1千多 说明什么 软件测试
  • 常见的端口服务及漏洞(详细)

    端口 对应的服务 存在的相关漏洞 21 69 ftp tftp 文件传输协议 爆破 嗅探溢出 后门 匿名访问 22 ssh 爆破 openssh漏洞 23 telnet 远程连接 爆破嗅探 25 smtp 邮件服务 弱口令 未授权访问 邮件
  • zookeeper+dubbo+springmvc,搭建

    Dubbo是一个分布式服务框架 在这基础上可以做成分布式计算机网络解决很多高并发或者数据处理量大的问题 二zookeeper又是dubbo的一个重要组件 在此 我借助java语言和springmvc框架介绍如何初步构建一个dubbo服务框架
  • 2023有哪些更好用的网页制作工具

    过去 专业人员使用HTMLL CSS Javascript等代码手动编写和构建网站 现在有越来越多的智能网页制作工具来帮助任何人实现零代码基础 随意建立和设计网站 在本文中 我们将向您介绍2023年流行的网页制作工具 我相信一旦选择了正确的
  • 网络安全技术期末复习——理论部分

    复习 考核 网络安全基本理论知识点 实际设备 网络安全实验 出勤 作业 讨论 课堂练习 11次课的作业完成情况 偏实践和操作 60 综合系统复习 理论考核 时间占三分之一 150分钟 理论就是50 操作100分钟 120分钟 理论40 操作
  • 匀速贝塞尔曲线运动的实现(转)

    二次贝塞尔曲线通常以如下方式构建 给定二维平面上的固定点P0 P1 P2 用B t 表示该条曲线 用一个动画来演示 可以更加清楚的表明这条曲线的构建过程如果t变量本身线形变化的话 这条贝塞尔曲线本身的生成过程是并不是匀速的 通常都是两头快中
  • 解决nodejs版本问题

    下载nvm 1 1 7 管理nodejs版本 下一步进行nodejs 安装 这里注意本人使用nvm1 1 9出现错误发现1 1 7较为好用 nvm use 选择使用版本 npm v 测试nodejs安装是否成功
  • React控制元素显示隐藏的三种方法

    React控制元素显示和隐藏的方法目前我知道的有三种方法 第一种是通过state变量来控制是否渲染元素 类似vue中的v if 第二种是通过style控制display属性 类似vue 中的v show 第三种是通过动态切换classNam
  • S11、反射系数、回波损耗

    S11是反射系数中的一种 以dB为单位的S11就是回波损耗 S11 Pr Pin S11等于反射功率除以入射功率 是功率比 将S11转换成以dB为单位 10 lgS11 系数 S11 dB 就是回波损耗 HFSS里S11就是这样表示的 ma
  • 问题记录整理(持续更新)

    文章目录 Java SSL SpringBoot Springboot项目配置jar外部静态文件 Swagger JPA SpringCloud Gateway 不能使用 web MVC框架 Feign 每个参数需要指定PathVariab
  • Vue之mitt事务总线使用方法

    npm install S mitt 1 组件总线 vue入口文件main js中挂载全局属性 导入vue创建命令 import createApp from vue 导入vue入口组件 import App from App vue 导入
  • CMake can not determine linker language for target: Intro

    cmake minimum required VERSION 3 9 project Intro C set CMAKE CXX STANDARD 11 add executable Intro main cpp 原来是一个C语言的项目 本
  • Css如何优雅的实现抽奖转盘

    如图 抽奖转盘 可以拆分为几部分 1 底部大圆 2 中间小圆 3 扇形区 4 扇形内部奖品区 5 抽奖按钮 6 点击抽奖按钮时旋转动效及逻辑 这其中 扇形区 以及扇形区内奖品的布局最为关键和麻烦 这个问题解决 剩下的问题 那都不是事儿 那如
  • 10种电脑无法启动故障

    开机自检时出现问题后会出现各种各样的英文短句 短句中包含了非常重要的信息 读懂这些信息可以自己解决一些小问题 可是这些英文难倒了一部分朋友 下面是一些常见的BIOS短句的解释 是我在修电脑时 常出现的短句 大家可以参考一下 1 CMOS b
  • Spring基础知识讲解

    文章目录 Spring是什么 IoC容器与DI DI与IoC的区别 Spring项目的创建 配置maven国内源 创建Spring项目 有关Bean的操作 存储Bean 使用Bean ApplicationContext和BeanFacto