Spring - 5 ( 8000 字 Spring 入门级教程 )

2024-04-25 23:44

本文主要是介绍Spring - 5 ( 8000 字 Spring 入门级教程 ),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一:Spring IoC&DI

1.1 方法注解 @Bean

类注解是添加到某个类上的, 但是存在两个问题:

  1. 使用外部包里的类, 没办法添加类注解
  2. ⼀个类, 需要多个对象, ⽐如多个数据源

这种场景, 我们就需要使用方法注解 @Bean

我们先来看方法注解如何使用:

public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
}

然而,当我们写完以上代码,尝试获取 bean 对象中的 user 时却发现,根本获取不到:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User user = context.getBean(User.class);//使⽤对象System.out.println(user);}
}

以上程序的执行结果如下:

在这里插入图片描述

这是为什么呢?

1.1.1 方法注解要配合类注解使用

在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:

@Component
public class BeanConfig {@Beanpublic User user(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}
}

再次执行以上代码,运行结果如下:

在这里插入图片描述

1.1.2 定义多个对象

对于同⼀个类, 如何定义多个对象呢,比如多数据源的场景, 类是同⼀个, 但是配置不同, 指向不同的数据源.

我们看下 @Bean 的使用

@Component
public class BeanConfig {@Beanpublic User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2(){User user = new User();user.setName("lisi");user.setAge(19);return user;}
}

定义了多个对象的话, 我们根据类型获取对象, 获取的是哪个对象呢?

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User user = context.getBean(User.class);//使⽤对象System.out.println(user);}
}

运行结果:
在这里插入图片描述

报错信息显示: 期望只有⼀个匹配, 结果发现了两个, user1, user2,从报错信息中, 可以看出来, @Bean 注解的 bean, bean 的名称就是它方法名

接下来我们根据名称来获取bean对象

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//根据bean名称, 从Spring上下⽂中获取对象User user1 = (User) context.getBean("user1");User user2 = (User) context.getBean("user2");System.out.println(user1);System.out.println(user2);}
}

运行结果:
在这里插入图片描述
可以看到, @Bean 可以针对同⼀个类, 定义多个对象.

1.1.3 重命名 Bean

可以通过设置 name 属性给 Bean 对象进行重命名操作,如下代码所示:

@Bean(name = {"u1","user1"})
public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;
}

@Bean(name = {“u1”,“user1”}) 这一行是 @Bean 注解的一种变体,它不仅定义了一个Bean,还给这个 Bean 起了两个不同的名字,分别是 u1 和 user1。

此时我们使用 u1 就可以获取到 User 对象了,如下代码示:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

1.2 扫描路径

使用前面学习的四个注解声明的 bean,⼀定会生效吗?答案是否定的,因为 bean 想要生效,还需要被 Spring 扫描

下⾯我们通过修改项目工程的目录结构,来测试 bean 对象是否生效:

在这里插入图片描述
再运行代码:

@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

运行结果:

在这里插入图片描述

报错原因:没有 bean 的名称为u1,为什么没有找到 bean 对象呢?

原因是使用五大注解声明的 bean,要想生效, 还需要配置扫描路径, 让 Spring 扫描到这些注解,也就是通过 @ComponentScan 来配置扫描路径.

@ComponentScan({"com.example.demo"})
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象User u1 = (User) context.getBean("u1");//使⽤对象System.out.println(u1);}
}

那为什么前⾯没有配置 @ComponentScan 注解也可以呢?

@ComponentScan 注解虽然没有显式配置,但是实际上已经包含在了启动类声明注解@SpringBootApplication 中了,默认扫描的范围是 SpringBoot 启动类所在包及其子包,在配置类上添加 @ComponentScan 注解, 该注解默认会扫描该类所在的包下所有的配置类

在这里插入图片描述
推荐做法:把启动类放在我们希望扫描的包的路径下, 这样我们定义的 bean 就都可以被扫描到

在这里插入图片描述

1.3 DI 详解

依赖注入是⼀个过程,是指 IoC 容器在创建 Bean 时, 去提供运行时所依赖的资源,而资源指的就是对象.

在上面程序案例中,我们使用了 @Autowired 这个注解,完成了依赖注入的操作,简单来说, 就是把对象取出来放到某个类的属性中.

关于依赖注入, Spring 也给我们提供了三种方式:

  1. 属性注入
  2. 构造方法注入
  3. Setter 注入

1.3.1 属性注入

属性注入是使⽤ @Autowired 实现的,将 Service 类注入到 Controller 类中.

  1. Service 类的实现代码如下:
import org.springframework.stereotype.Service;
@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}
  1. Controller 类的实现代码如下:
@Controller
public class UserController {//注⼊⽅法1: 属性注⼊@Autowiredprivate UserService userService;public void sayHi() {System.out.println("hi,UserController...");userService.sayHi();}
}
  1. 获取 Controller 中的 sayHi⽅法:
@SpringBootApplication
public class SpringIocDemoApplication {public static void main(String[] args) {//获取Spring上下⽂对象ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);//从Spring上下⽂中获取对象UserController userController = (UserController) context.getBean("Controller");//使⽤对象userController.sayHi();}
}

最终结果如下:

在这里插入图片描述

去掉 @Autowired , 再运行一下程序看看结果

在这里插入图片描述

1.3.2 构造方法注入

构造方法注入是在类的构造方法中实现注入,如下代码所示:

@Controller
public class UserController2 {//注⼊⽅法2: 构造⽅法private UserService userService;@Autowiredpublic UserController2(UserService userService) {this.userService = userService;}public void sayHi(){System.out.println("hi,UserController2...");userService.sayHi();}
}

注意事项:如果类只有⼀个构造方法,那么 @Autowired 注解可以省略;如果类中有多个构造方法,那么需要添加上 @Autowired 来明确指定到底使用哪个构造方法。

1.3.3 Setter 注入

Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解 ,如下代码所示:

@Controller
public class UserController3 {//注⼊⽅法3: Setter⽅法注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void sayHi(){System.out.println("hi,UserController3...");userService.sayHi();}
}

1.3.4 三种注入优缺点分析

第一种:属性注入

优点:

  • 简洁,使用方便

缺点:

  • 只能用于 IoC 容器,如果是非 IoC 容器不可用,并且只有在使用的时候才会出现 NPE(空指针异常)
  • 不能注入一个 Final 修饰的属性

第二种:构造函数注入 (Spring 4.X 推荐)

优点:

  • 可以注入 final 修饰的属性
  • 注入的对象不会被修改
  • 依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法。
  • 通用性好,构造方法是 JDK 支持的,所以更换任何框架都适用

缺点:

  • 注入多个对象时,代码会比较繁琐

第三种:Setter 注入 (Spring 3.X 推荐)

优点

  • 方便在类实例之后,重新对该对象进行配置或者注入

缺点:

  • 不能注入一个 Final 修饰的属性
  • 注入对象可能会被改变,因为 setter 方法可能会被多次调用,就有被修改的风险

1.3.5 @Autowired 存在问题

当同⼀类型存在多个 bean 时, 使⽤ @Autowired 会存在问题

@Component
public class BeanConfig {@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}
@Controller
public class UserController {@Autowiredprivate UserService userService;//注⼊user@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();System.out.println(user);}
}

运行结果:
在这里插入图片描述
报错的原因是,非唯⼀的 Bean 对象,如何解决上述问题呢?Spring 提供了以下几种解决方案:

  • @Primary
  • @Qualifier
  • @Resource

下面 一 一 进行讲解

  1. 使用 @Primary 注解:当存在多个相同类型的 Bean 注入时,加上 @Primary 注解,来确定默认的实现.
@Component
public class BeanConfig {@Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User user2() {User user = new User();user.setName("lisi");user.setAge(19);return user;}
}
  1. 使用 @Qualifier 注解:指定当前要注入的 bean 对象。 在 @Qualifier 的 value 属性中,指定注入的 bean 的名称。

注意:@Qualifier 注解不能单独使用,必须配合 @Autowired 使用

@Controller
public class UserController {@Qualifier("user2") //指定bean名称@Autowiredprivate User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}
  1. 使用 @Resource 注解:是按照 bean 的名称进行注入。通过 name 属性指定要注入的 bean 的名称。
@Controller
public class UserController {@Resource(name = "user2")private User user;public void sayHi(){System.out.println("hi,UserController...");System.out.println(user);}
}

@Autowird 与 @Resource 的区别

  • @Autowired 是 spring 框架提供的注解,而 @Resource 是 JDK 提供的注解

  • @Autowired 默认是按照类型注入,而 @Resource 是按照名称注入.

相比于 @Autowired 来说,@Resource 支持更多的参数设置,例如 name 设置,根据名称获取 Bean。

1.4 总结

Spring, Spring Boot 和 Spring MVC 的关系以及区别:

  1. Spring:

简单来说, Spring 是⼀个开发应用框架,目的是用于简化企业级应用程序开发.

  1. Spring MVC:

Spring MVC 是 Spring 的⼀个子框架, Spring 诞生之后, 大家觉得很好用, 于是按照MVC模式设计了⼀个 MVC 框架,用于开发 web 应用和网络接口。

  1. Spring Boot:

Spring Boot 是对 Spring 的⼀个封装, 为了简化 Spring 用的开发而出现的,中小型企业,没有成本研究自己的框架, 使用 Spring Boot 可以更加快速的搭建框架, 降级开发成本, 让开发人员更加专注于 Spring 应用的开发,而无需过多关注 XML 的配置和⼀些底层的实现.

Spring, Spring Boot 和 Spring MVC 的功能:

  1. Spring

spring 主要用于管理对象和对象之间的依赖关系

  1. Spring MVC

基于 Spring 进行开发的, 天生的与 Spring 框架集成. 可以让我们更简洁的进行 Web 层开发, 支持灵活的 URL 到页面控制器的映射

  1. Spring Boot

Spring Boot 是个脚手架, 插拔式搭建项⽬, 可以快速的集成其他框架进来,比如想使用SpringBoot 开发 Web 项目, 只需要引入 Spring MVC 框架即可

  1. ⼀句话总结

Spring MVC 和 Spring Boot 都属于 Spring,Spring MVC 是基于 Spring的⼀个MVC 框架,而 Spring Boot 是基于 Spring 的⼀套快速开发整合包.

比如我们的图书系统代码中:

  • 整体框架是通过 SpringBoot 搭建的
  • IoC, DI 功能是 Spring 的提供的,
  • web 相关功能是 Spring MVC 提供的

这三者专注的领域不同,解决的问题也不⼀样, 总的来说,Spring 就像⼀个大家族,有众多衍生产品, 但他们的基础都是 Spring

在这里插入图片描述

在这里插入图片描述

这篇关于Spring - 5 ( 8000 字 Spring 入门级教程 )的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/936124

相关文章

windos server2022的配置故障转移服务的图文教程

《windosserver2022的配置故障转移服务的图文教程》本文主要介绍了windosserver2022的配置故障转移服务的图文教程,以确保服务和应用程序的连续性和可用性,文中通过图文介绍的非... 目录准备环境:步骤故障转移群集是 Windows Server 2022 中提供的一种功能,用于在多个

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、