Spring基础知识讲解

news2024/10/3 8:17:51

文章目录

  • Spring是什么?
    • IoC容器与DI
      • DI与IoC的区别
  • Spring项目的创建
    • 配置maven国内源
    • 创建Spring项目
    • 有关Bean的操作
      • 存储Bean
      • 使用Bean
    • ApplicationContext和BeanFactory的区别
    • getBean()的三种使用方法
  • 更简单的存储和获取对象
    • 类注解
    • 方法注解
    • 获取Bean对象的简单方法——依赖注入
      • @Autowired和@Resource的区别
  • Bean的作用域和生命周期
    • 作用域
    • 设置作用域
    • 生命周期
      • Bean的执行流程
      • Bean的生命周期

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、初始化的后置方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/787739.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu18.04下安装ROS

安装相关依赖 sudo apt install ninja-build exiftool ninja-build protobuf-compiler libeigen3-dev genromfs xmlstarlet libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev python-pip python3-pip ----------------------------------------------------------------…

TCP/IP 介绍

一、TCP/IP 是什么 TCP /IP 是因特网通信协议 &#xff08;注释&#xff1a;通信协议是对计算机必须遵守的规则的描述&#xff0c;只有遵守这些规则&#xff0c;计算机之间才能进行通信。&#xff09; 因特网浏览器和因特网服务器均使用 TCP/IP 来连接因特网。浏览器使用 TCP…

Idea 避免import *

File -> setting -> Editor -> Code Style -> Java -> Imports

详解Mybatis查询之resultType返回值类型问题【4种情况】

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 Mybatis版本&#xff1a;3.5.6 文章目录 引言一、查询单行数据返回单个对象二、查询多行数据返回对象的集合三、 查询单行数据返回Map[Key,…

pandas学习

(个人学习使用) 添加索引 # index是行索引&#xff0c;columns是列索引 pd.DataFrame(score, indexidx, columnscol) 常用属性和方法 data.shape # 形状 data.index # 行索引 data.columns # 列索引 data.values # 里面的值&#xff0c;结果是ndarray类型数组 …

SpringBoot登陆+6套主页-【JSB项目实战】

SpringBoot系列文章目录 SpringBoot知识范围-学习步骤【JSB系列之000】 文章目录 SpringBoot系列文章目录本系列校训 SpringBoot技术很多很多环境及工具&#xff1a;上效果图主页登陆 配置文件设置导数据库项目目录如图&#xff1a;代码部分&#xff1a;控制器过滤器详细的解…

docker Registry私有仓库

一、docker自带的本地私有仓库配置 #首先下载registry镜像 docker pull registry#在daemon.json文件中添加私有仓库地址 vim /etc/docker/daemon.json {"insecure-registries": ["192.168.60.11:5000"], #添加&#xff0c;注意用逗号结尾"registr…

验证码登录如何实现?

手机验证码登录 1、需求分析2、数据模型3、代码开发-交互过程4、代码开发-准备工作5、代码开发-修改LoginCheckFilter6、代码开发-接口开发7、前端代码介绍8、启动测试 1、需求分析 为了方便用户登录&#xff0c;移动端通常都会提供通过手机验证码登录的功能。 手机验证码登录…

Android性能优化之修复游戏中内存泄漏(java层)

游戏在bugly上内存OOM越来越严重&#xff0c;因此&#xff0c;近期对内存进行优化。从java层的内存进行优化开始&#xff0c;通过LeakCannary或者adb shell 获取到内存快照&#xff0c;发现好几处内存泄漏点。 1.单例类持有Activity&#xff1a; 查看内存快照&#xff0c;该闪…

MFC第二十天 数值型关联变量 和单选按钮与复选框的开发应用

文章目录 数值型关联变量数值型关联变量的种类介绍 单选按钮与复选框单选按钮的组内选择原理解析单选按钮和复选框以及应用数值型关联变量的开发CMainDlg.cppCInputDlg.hCInputDlg.cpp 附录 数值型关联变量 数值型关联变量的种类介绍 1、 数值型关联变量&#xff1a; a)控件型…

STM32MP157驱动开发——按键驱动(异步通知)

文章目录 “异步通知 ”机制&#xff1a;信号的宏定义&#xff1a;信号注册 APP执行过程驱动编程做的事应用编程做的事异步通知方式的按键驱动程序(stm32mp157)button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “异步通知 ”机制&#xff1a; 信号的宏定义&#x…

请问学JavaScript 前要学html 和css 吗?

前言 html和css可以理解为是一个网站的骨架和皮肤&#xff0c;这两部分做好后整个网站的外观展示的完成度基本就有了个90%左右&#xff0c;所以在学习js前是需要学习html和css 的&#xff0c;这两部分不用花特别多的时间&#xff08;虽然css如果想做一些非常炫酷的效果个人认为…

记一次容器环境下出现 Address not available

作者&#xff1a;郑明泉、余凯 困惑的源地址 pod 创建后一段时间一直是正常运行&#xff0c;突然有一天发现没有新的连接创建了&#xff0c;业务上是通过 pod A 访问 svc B 的 svc name 的方式&#xff0c;进入 pod 手动去 wget 一下&#xff0c;发现报错了 Address not avai…

Roslyn 动态编译

NET 编译器平台&#xff08;.NET Compiler Platform&#xff09; 也称为Roslyn&#xff0c;是Microsoft的一组用于C#和Visual Basic (VB.NET) 语言的开源 编译器和代码分析 API。 该项目特别包括C# 和 VB.NET 编译器的自托管版本——用语言本身编写的编译器。编译器可通过传统…

vue2路由(个人学习笔记四)

目录 友情提醒第一章、路由简介1.1&#xff09;什么是路由1.2&#xff09;安装路由插件 第二章、自定义路由器2.1&#xff09;创建路由器文件index.js文件2.2&#xff09;index.js文件中配置路由信息 第三章、使用路由器3.1&#xff09;在main.js文件中将路由器绑定到Vue对象3.…

查看maven发布时间的方法

查看maven发布时间的方法如下【 打开maven官网 选中Release Notes 即可查看对应版本的发布时间 】

【Linux命令200例】cmp文件比较工具

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;本文已收录于专栏&#xff1a;Linux命令大全。 &#x1f3c6;本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

微信小程序开发知识点总结(不断补充)

一、怎样实现小程序与数据库的交互原理 微信小程序开发里面是不能直接写数据库连接文件&#xff0c;如果要实现与数据库的交互&#xff0c;就需要用到中间的接口。&#xff08;这个接口可以理解成springboot项目中controller层的RequestMapping的URL&#xff09;具体用法如下&…

Thunderbird 115 带来了Supernova UI 和先进功能

导读Thunderbird 115 带来了Supernova UI 和先进功能&#xff0c;将电子邮件带入了新的高度。 流行的开源电子邮件客户端 Mozilla Thunderbird 推出了最新版本Thunderbird 115&#xff0c;它带来了一系列令人兴奋的功能和改进。更新带来了令人耳目一新的超新星用户界面(UI)&…

STM32MP157驱动开发——按键驱动(线程化处理)

文章目录 “线程化处理”机制&#xff1a;内核函数线程化处理方式的按键驱动程序(stm32mp157)编程思路button_test.cgpio_key_drv.cMakefile修改设备树文件编译测试 “线程化处理”机制&#xff1a; 工作队列是在内核的线程的上下文中执行的 工作队列中有多个 work&#xff0…