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

相关文章

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让