【 Spring IOC&DI】
方法注解@Bean
一、方法注解 @Bean
类注解是添加到某个类上的,但存在两个问题:
- 使用外部包里的类,没办法添加类注解
- 一个类,需要多个对象,比如多个数据源
这种场景,我们就需要使用方法注解 @Bean
1.1使用
在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中,如下代码所示:
@Component
public class BeanConfig {
@Bean
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
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);
}
}
1.2定义多个对象
比如多数据源的场景,类是同一个,但是配置不同,指向不同的数据源。
我们看下 @Bean 的使用:
@Component
public class BeanConfig {
@Bean
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
return user;
}
@Bean
public User user2(){
User user =new User();
user.setName("lisi");
user.setAge(20);
return user;
}
}
获取对象:
@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);
}
}
1.3重命名Bean
可以通过设置 name 属性给 Bean 对象进行重命名操作,如下代码所示:
@Component
public class BeanConfig {
@Bean(name = {"u1","uer1"})
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
return user;
}
1.3.1name={} 可以省略
@Bean({"u1","user1"})
public User user1(){
User user = new User(); user.setName("zhangsan");
user.setAge(18);
return user;
}
1.3.2只有一个名称时,{} 也可以省略
@Component
public class BeanConfig {
@Bean("u1")
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
return user;
}
一、IOC&DI入门
1.1什么是spring
一句话:spring就是包含了众多工具方法的IOC容器
Spring:Java 开发的 “对象管家”,核心是 IoC 和 AOP
1.2什么是IOC
IoC是Spring的核⼼思想,也是常⻅的⾯试题,那什么是IoC呢?
IOC:控制反转,也就是说spring是一个“控制反转”的容器。
控制反转是一种思想,比如自动驾驶把驾驶权交给系统。
IoC 控制反转,就是将对象的控制权交给 Spring 的 IOC 容器,由 IOC 容器创建及管理对象,也就是 bean 的存储。
1.3什么是DI
DI:Dependency Injection(依赖注入)
容器在运行期间,动态的为应用程序提供运行时所依赖的资源。称之为依赖注入。
IoC 是一种思想,也是 “目标”,而思想只是一种指导原则,最终还是要有可行的落地方案,而 DI 就属于具体的实现。所以也可以说,DI 是 IoC 的一种实现。
二、IoC & DI 使用
对 IoC 和 DI 有了初步的了解,我们接下来具体学习 Spring IoC 和 DI 的代码实现。
既然 Spring 是一个 IoC (控制反转) 容器,作为容器,那么它就具备两个最基础的功能:
- 存
- 取
Spring 容器管理的主要是对象,这些对象,我们称之为 “Bean”。我们把这些对象交由 Spring 管理,由 Spring 来负责对象的创建和销毁。我们程序只需要告诉 Spring,哪些需要存,以及如何从 Spring 中取出对象
2.1Bean 的存储
共有两类注解类型可以实现:
- 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
- 方法注解:@Bean。
2.1.1@Controller (控制器存储)
使用 @Controller 存储 bean 的代码如下所示:
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
//存储对象到spring中
@Controller
public class UserController {
public void sayHi(){
System.out.println("hi,Controller...");
}
}
如何从 Spring 容器中获取对象
package com.example.demo;
import com.example.demo.controller.UserController;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//启动 Spring 应用,获取spring上下文对象
ApplicationContext context=
SpringApplication.run(SpringIocDemoApplication.class, args);
//从上下文中获取 UserController 这个 Bean
UserController userController=context.getBean(UserController.class);
//使用对象
userController.sayHi();
}
}
`
ApplicationContext 是 Spring 框架中核心的上下文对象,可以理解为Spring 容器的 “总管家”,它负责管理所有由 Spring 托管的对象(即 “Bean”),并提供了一系列功能来操作这些对象。
它的核心作用
- 管理 Bean 的生命周期:负责 Bean 的创建、初始化、销毁等全流程。
- 提供 Bean 的获取方式:通过 getBean() 方法可以从容器中获取任意已注册的 Bean(就像代码中获取
UserController 一样)。- 支持依赖注入:自动帮你解决对象之间的依赖关系(比如 A 类依赖 B 类,Spring 会自动把 B 注入到 A 中)。
提供资源访问、事件发布等扩展功能。
2.1.1.1获取 bean 对象的其他方式
ApplicationContext 也提供了其他获取 bean 的方式,ApplicationContext 获取 bean 对象的功能,是父类 BeanFactory 提供的功能。
1、2、4方法是常用的
2.1.1.2Bean命名约定
- 类名的小驼峰
- 特殊情况,类名前面两位大写字母,Bean即类名
比如:
类名: UserController,Bean 的名称为: userController
类名: UController,Bean 的名称为: UController
2.1.1.3ApplicationContext VS BeanFactory (常见面试题)
- 继承关系和功能方面来说:Spring 容器有两个顶级的接口:BeanFactory 和 ApplicationContext。
其中 BeanFactory 提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,它除了继承了 BeanFactory 的所有功能之外,它还拥有独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面的支持。
- 从性能方面来说:ApplicationContext 是一次性加载并初始化所有的 Bean 对象,而 BeanFactory
是需要那个才去加载那个,因此更加轻量. (空间换时间)
2.1.2@Servie&@Repository&@Configuration
它们的使用与@Controller一样
2.2各种类注解的作用
@Controller: 控制层,接收请求,对请求进行处理,并进行响应.
@Service: 业务逻辑层,处理具体的业务逻辑.
@Repository: 数据访问层,也称为持久层。负责数据访问操作
@Configuration: 配置层。处理项目中的一些配置信息.
程序的应用分层,调用流程如下:前端 → @Controller → @Service → @Repository → 数据库;@Configuration 用于配置层
2.2.1类注解之间的关系
其实这些注解里面都有一个注解 @Component,说明它们本身就是属于 @Component 的 “子类”.@Component 是一个元注解,也就是说可以注解其他类注解,如 @Controller , @Service , @Repository 等。这些注解被称为 @Component 的衍生注解.@Controller , @Service 和 @Repository 用于更具体的用例 (分别在控制层,业务逻辑层,持久化层)
一、依赖注入(DI)细节
依赖注入是一个过程,是指 IoC 容器在创建 Bean 时,去提供运行时所依赖的资源,而资源指的就是对象。
关于依赖注入,Spring 也给我们提供了三种方式:
- 属性注入 (Field Injection)
- 构造方法注入 (Constructor Injection)
- Setter 注入 (Setter Injection)
接下来,我们分别来看。
二、属性注入
属性注入是使用 @Autowired 实现的,将 Service 类注入到 Controller 类中。
Service 类的实现代码如下:
@Service
public class UserService {
public void sayHi(){
System.out.println("hi,Service...");
}
}
Controller 类的实现代码如下:
//存储对象到spring中
@Controller
public class UserController {
//注入方法1:属性注入
@Autowired
private UserService userService;
public void sayHi(){
System.out.println("hi,Controller...");
userService.sayHi();
}
}
获取 Controller 中的 sayHi 方法:
@SpringBootApplication
public class SpringIocDemoApplication {
public static void main(String[] args) {
//启动 Spring 应用,获取spring上下文对象
ApplicationContext context=
SpringApplication.run(SpringIocDemoApplication.class, args);
//从上下文中获取 UserController 这个 Bean
UserController userController=context.getBean(UserController.class);
//使用对象
userController.sayHi();
}

三、构造方法注入
构造方法注入是在类的构造方法中实现注入,如下代码所示:
@Autowired不是 “属性注解”,而是加在构造方法上的注解,作用是告诉 Spring:“用这个构造方法来创建UserController2对象,并自动注入UserService参数”
@Controller
public class UserController2 {
//注入方法2:构造方法
private UserService userService;
@Autowired
public UserController2(UserService userService){
this.userService=userService;
}
public void sayHi(){
System.out.println("hi,UserController2...");
userService.sayHi();
}
}
注意事项:如果类只有一个构造方法,那么 @Autowired 注解可以省略;如果类中有多个构造方法,那么需要添加上 @Autowired 来明确指定到底使用哪个构造方法。
四、Setter 注入
Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set 方法的时候需要加上 @Autowired 注解,如下代码所示:
@Controller
public class UserController3 {
//注入方法3:Setter方法注入
private UserService userService;
@Autowired
public void setUserService(UserService userService){
this.userService=userService;
}
public void sayHi(){
System.out.println("hi,UserController3...");
userService.sayHi();
}
五、 三种注入优缺点分析
1. 属性注入
优点:简洁,使用方便;
缺点:
- 只有用 Spring 框架(IoC 容器)时才能用,换成其他框架(比如自己写普通 Java 项目)就没用了;
- 你写的类创建出来时,属性是null,只有当你调用这个属性的方法时,才会发现
“空指针”(比如你没注入UserService,但调用了userService.sayHi(),这时候才报错)。 - 不能注入一个 Final 修饰的属性
如果属性加了final(比如private final UserService userService;),属性注入搞不定 —— 因为final属性必须在 “对象创建时” 赋值,而属性注入是 “对象创建之后” 才赋值的。
2.构造函数注入 (Spring 4.X 推荐)
优点:
-
可以注入 final 修饰的属性
-
注入的对象不会被修改
构造方法只执行一次(创建对象时),赋值后属性可以设为private final,后续没人能改这个属性的值,安全。 -
依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的方法
-
通用性好,构造方法是 JDK 支持的,所以更换任何框架,他都是适用的
缺点:
注入多个对象时,代码会比较繁琐
3.Setter 注入 (Spring 3.X 推荐)
优点:方便在类实例之后,重新对该对象进行配置或者注入
缺点:
- 不能注入一个 Final 修饰的属性
- 注入对象可能会被改变,因为 setter 方法可能会被多次调用,就有被修改的风险
4.怎么选?
想简单省事儿、依赖少:用属性注入;
想安全、通用、依赖多:用构造方法注入(Spring 官方推荐);
想后续能改依赖:用Setter 注入。
更多 DI 相关内容参考: Dependencies:: Spring Framework
六、@Autowired 存在的问题
当同一类型存在多个 bean 时,使用 @Autowired 会存在问题
@Component
public class BeanConfig {
@Bean()
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
return user;
}
@Bean
public User user2(){
User user =new User();
user.setName("lisi");
user.setAge(20);
return user;
}
}
//存储对象到spring中
@Controller
public class UserController {
//注入方法1:属性注入
@Autowired
private UserService userService;
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,Controller...");
userService.sayHi();
System.out.println(user);
}
}
运行结果:报错的原因是,非唯一的 Bean 对象。
Spring 提供了以下几种解决方案:
- @Primary
- @Qualifier
- @Resource
6.1使用 @Primary 注解
使用 @Primary 注解:当存在多个相同类型的 Bean 注入时,加上 @Primary 注解,来确定默认的实现。
@Component
public class BeanConfig {
@Primary//指定该bean为默认bean的实现
@Bean
public User user1(){
User user =new User();
user.setName("zhangsang");
user.setAge(20);
return user;
}
@Bean
public User user2(){
User user =new User();
user.setName("lisi");
user.setAge(20);
return user;
}
}

6.2使用 @Qualifier 注解
使用 @Qualifier 注解:指定当前要注入的 bean 对象。在 @Qualifier 的 value 属性中,指定注入的 bean 的名称。
@Qualifier 注解不能单独使用,必须配合 @Autowired 使用
@Component
//存储对象到spring中
@Controller
public class UserController {
//注入方法1:属性注入
@Autowired
private UserService userService;
@Autowired
@Qualifier("user2")
private User user;
public void sayHi(){
System.out.println("hi,Controller...");
userService.sayHi();
System.out.println(user);
}
}
6.3使用 @Resource 注解
使用 @Resource 注解:是按照 bean 的名称进行注入。通过 name 属性指定要注入的 bean 的名称。
//存储对象到spring中
@Controller
public class UserController {
//注入方法1:属性注入
@Autowired
private UserService userService;
@Autowired
@Resource(name="user2")
private User user;
public void sayHi(){
System.out.println("hi,Controller...");
userService.sayHi();
System.out.println(user);
}
}
6.4常见面试题
@Autowired 与 @Resource 的区别
- @Autowired 是 spring 框架提供的注解,而 @Resource 是 JDK 提供的注解
- @Autowired 默认是按照类型注入,而 @Resource 是按照名称注入。相比于 @Autowired 来说,@Resource
支持更多的参数设置,例如 name 设置,根据名称获取 Bean
Autowired 装配顺序
七、总结
7.1 Spring,SpringBoot和Spring MVC的关系以及区别
Spring: 简单来说,Spring 是一个开发应用框架,它有轻量级、一站式、模块化这几个标签,其目的是用于简化企业级应用程序开发。
Spring 的主要功能: 管理对象,以及对象之间的依赖关系、面向切面编程、数据库事务管理、数据访问、web 框架支持等。
但是 Spring 具备高度可开放性,并不强制依赖 Spring,开发者可以自由选择 Spring 的部分或者全部,Spring 可以无缝集成第三方框架,比如数据访问框架(Hibernate、JPA)、web 框架(如 Struts、JSF)。
Spring MVC: Spring MVC 是 Spring 的一个子框架,Spring 诞生之后,大家觉得很好用,于是按照 MVC 模式设计了一个 MVC 框架(一些用 Spring 解耦的组件),主要用于开发 WEB 应用和网络接口,所以,Spring MVC 是一个 Web 框架。
Spring MVC 基于 Spring 进行开发的,天生的与 Spring 框架集成。可以让我们更简洁的进行 Web 层开发,支持灵活的 URL 到页面控制器的映射,提供了强大的约定大于配置的契约式编程支持,非常容易与其他视图框架集成,如 Velocity、FreeMarker 等。
Spring Boot: Spring Boot 是对 Spring 的一个封装,为了简化 Spring 应用的开发而出现的。中小型企业没有成本研究自己的框架,使用 Spring Boot 可以更加快速的搭建框架,降低开发成本,让开发人员更加专注于 Spring 应用的开发,而无需过多关注 XML 的配置和一些底层的实现。
Spring Boot 是个脚手架,插拔式搭建项目,可以快速的集成其他框架进来。
比如想使用 SpringBoot 开发 Web 项目,只需要引入 Spring MVC 框架即可,Web 开发的工作是 SpringMVC 完成的,而不是 SpringBoot;想完成数据访问,只需要引入 Mybatis 框架即可。
Spring Boot 只是辅助简化项目开发的,让开发变得更加简单,甚至不需要额外的 web 服务器,直接生成 jar 包执行即可。
最后一句话总结:Spring MVC 和 Spring Boot 都属于 Spring,Spring MVC 是基于 Spring 的一个 MVC 框架,而 Spring Boot 是基于 Spring 的一套快速开发整合包。
7.2 bean 的命名
- 五大注解存储的 bean
① 前两位字母均为大写,bean 名称为类名
② 其他的为类名首字母小写
③ 通过 value 属性设置 @Controller (value = “user”)
- @Bean 注解存储的 bean
① bean 名称为方法名
② 通过 name 属性设置 @Bean (name = {“u1”,“user1”})
7.3 常见面试题
- 三种注入方式的优缺点(如上)
- 常见注解有哪些?分别是什么作用?
web url 映射:@RequestMapping
参数接收和接口响应:@RequestParam、@RequestBody、@ResponseBody
bean 的存储:@Controller、@Service、@Repository、@Component、@Configuration、@Bean
bean 的获取:@Autowired、@Qualifier、@Resource - @Autowired 和 @Resource 区别
- 说下你对 Spring、SpringMVC、Springboot 的理解(如上)
一、什么是 Spring Web MVC?
Spring MVC 是 Spring 框架的核心模块之一,基于 MVC(Model-View-Controller)设计模式 实现,专为解决 Java Web 开发中的请求处理、视图渲染、数据交互等问题而生。它不仅简化了 Web 应用的开发流程,还提供了松耦合、易扩展的架构设计,是企业级 Java Web 开发的主流选择。
从上述定义我们可以得出⼀个信息:Spring Web MVC 是⼀个Web框架.
1.1 MVC定义
MVC 是ModelViewController的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分
- View(视图):指在应⽤程序中专⻔⽤来与浏览器进⾏交互,展⽰数据的资源
- Model(模型):是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分.
- Controller(控制器:可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型
1.2什么是Spring MVC?
MVC是一种框架设计模式,也是一种思想,而Spring MVC是对MVC的具体实现,是一个web框架。
在创建springboot项目时,勾选的spring web框架就是springmvc框架。
二、学习Spring MVC
既然是 Web 框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求,并给予响应。
主要分以下三个方面:
建立连接:将用户(浏览器)和 Java 程序连接起来,也就是访问一个地址能够调用到我们的 Spring 程序。
请求:用户请求的时候会带一些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能。
响应: 执行了业务逻辑之后,要把程序执行的结果返回给用户,也就是响应。
比如用户去银行存款:
- 建立连接:去柜台
- 请求:带着银行卡、身份证去存款
- 响应:银行返回一张存折。
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC。
2.1项目准备
Spring MVC项目创建和Spring boot创建项目相同,创建时选择Spring web即可。
2.2建立连接
在Spring MVC中使用 @RequestMapping 来实现URL路由映射(浏览器连接程序的作用)。
创建一个HelloController类,实现用户通过浏览器和程序进行交互。
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/hello")
public class HelloController {
@RequestMapping("/word")
public String heloo(){
System.out.println("hello ,Spring boot!");
return "hello ,Spring boot!";
}
}
访问:http://127.0.0.1:8080/hello/word
2.2.1 @RequestMapping注解
在 Spring Web MVC 应用程序中,@RequestMapping 是最常用的注解之一,其核心作用是注册接口的路由映射。路由映射 :当用户访问一个 URL 时,将这个请求对应到程序中某个类的某个方法的过程
具体来说,当服务接收到请求时,若请求路径与 @RequestMapping 中配置的路径匹配,就会自动调用该注解所修饰的方法执行对应代码。
疑问:既然 @RequestMapping 已经能实现路由映射,为什么还需要添加 @RestController 注解呢
测试一下去掉 @RestController
状态码:404,找不到该页面

原因在于:一个 Spring 项目中会包含大量类,每个类又可能有多个方法。Spring 并不会默认扫描所有类和方法来匹配请求 —— 只有当某个类添加了 @RestController 注解时,Spring 才会对这个类进行 “重点扫描”,进而检查该类内部的方法是否添加了 @RequestMapping(或其他请求相关注解),并建立请求与方法的对应关系。
2.2.2@RequestMapping使用
@RequestMapping 既是类注解,又是方法注解
访问url:类路径+方法路径
2.2.3@RequestMapping是什么请求
HTTP请求方式:get,post,put, delete、、、
浏览器发送的都是get请求
@RequestMapping 既⽀持Get请求,⼜⽀持Post请求.同理,也⽀持其他的请求⽅式.
2.3请求
访问不同的路径,就是发送不同的请求.在发送请求时,可能会带⼀些参数,所以学习Spring的请求,主要是学习如何传递参数到后端以及后端如何接收.
2.3.1传递单个参数
@RequestMapping("/request")
@Controller
public class RequestController {
//单个参数
@RequestMapping("/login")
public String login(String name) {
return "接收参数name:" + name;
}

Spring MVC 会根据⽅法的参数名,找到对应的参数,赋值给⽅法,参数名要一致
参数名不一致
使用基本类型接收参数时,参数必须传(除boolean),否则会报500错误,类型不匹配时报400错误
//基本类型接收参数
@RequestMapping("/m1")
public Object getInt(int age) {
return "接收到参数age:" + age;
}

报400看一下日志

2.3.2传递多个参数
@RequestMapping("/m1")
public Object getInt(String name, String password) {
return "接收到参数name:" + name + " password:" + password;
}

2.3.3传递对象
当参数比较多时,方法声明就需要有很多形参,并且后续每次新增一个参数,也需要修改方法声明。我们不妨把这些参数封装为一个对象,Spring MVC 也可以自动实现对象参数的赋值,比如 Person 对象。
package com.example.demo;
public class Person {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
传递对象代码实现
@RequestMapping("/m2")
//传递对象
public Object method2(Person p) {
return p.toString();
}

2.3.4后端参数重命名
在某些特殊情况下,前端传递的参数 key 和后端接收的 key 可能不一致。例如,前端传递了一个 time 给后端,而后端使用 createtime 字段来接收,这会导致参数接收不到。此时,我们可以使用 @RequestParam 来重命名前后端的参数值。
@RequestMapping("/m3")
//后端参数重命名(后端参数映射)注释
public Object method3(@RequestParam( "time") String goodtime) {
return "接收参数good time:" + goodtime;
}

前端用goodtime传参
报400错误
查看日志
请求参数“time”不存在
得出以下结论:
- 使用 @RequestParam 进行参数重命名时,请求参数只能和 @RequestParam 声明的名称一致,才能进行参数绑定和赋值。
- 使用 @RequestParam 进行参数重命名时,参数会变成必传参数。
不想变成必传参数可以设置成false
@RequestMapping("/m3")
//后端参数重命名(后端参数映射)注释
public Object method3(@RequestParam(value = "time", required = false) String goodtime) {
return "接收参数good time:" + goodtime;
}
2.3.5传递数组
@RequestMapping("/m4")
//传递数组
public String method4(String[] arry) {
return Arrays.toString(arry);
}

2.4.6传递集合
集合参数:和数组类似,同一个请求参数名有多个值,且需要使用 @RequestParam 绑定参数关系。
@RequestMapping("/m5")
//传递集合
public String method5(@RequestParam List<String> listParam) {
return "size:" + listParam.size() + ",listParam:" + listParam;
}

2.37传递JSON数据
JSON 的语法:
- 数据在键值对(Key/Value)中
- 数据由逗号(,)分隔
- 对象用({})表示
- 数组用([])表示
- 值可以为对象,也可以为数组,数组中可以包含多个对象
JSON 的两种结构:
- 对象:大括号({})保存的对象是一个无序的键值对集合。一个对象以左括号({)开始,右括号(})结束。每个 “键”
后跟一个冒号(:),键值对使用逗号(,)分隔。 - 数组:中括号([])保存的数组是值(value)的有序集合。一个数组以左中括号([)开始,右中括号(])结束,值之间使用逗号(,)分隔。
下面是合法的JSON数据
{"name":"admin","age":18}
["hello", 3.1415, "json"]
[{"name":"admin","age":18},{"name":"root","age":16},{"name":"张三","age":20}]
后端实现
@RequestMapping("/m6")
//json对象
public Object method6(@RequestBody Person person) {
return person.toString();
}

2.3.8获取URL中参数@PathVariable
@RequestMapping("/m8/{id}/{name}")
//获取URL中参数@PathVariable
public String method8(@PathVariable Integer id, @PathVariable String name) {
return "解析参数id:" + id + ",name:" + name;
}

2.3.9上传文件@RequestPart
@RequestMapping("/m9")
public String method9(@RequestPart("file") MultipartFile file) throws IOException {
//获取⽂件名称
String fileName = file.getOriginalFilename();
//⽂件上传到指定路径
file.transferTo(new File("D:/temp/" + file.getOriginalFilename()));
return "接收到⽂件名称为: " + fileName;
}
总结
以上就是今天要讲的内容,上面的笔记讲了SpringMVC建立连接和请求的相关注释和用法,下一篇文章会写响应。
项目场景:
新建一个springboot项目
问题描述&原因分析&解决方法
1、问题:依赖爆红


分析:包为下载下来,重新刷新Maven
解决:包未下载下来
- 再次刷新,多次刷新maven
- 删除本地仓库,下载了一半的jar包,再刷新一下
- 自查一下是不是网络问题,切换一下网络
- 休息一会,过会刷新
- 以上方法不行考虑清一下idea缓存
2、问题:pom.xml 文件没有报错但依赖导入未成功,Cannot resolve symbol ‘springframework’

分析:代码中大量出现 “Cannot resolve symbol’springframework’” 这类错误,原因很可能是Spring 相关依赖没有正确导入到项目中。
解决:
- 检查pom.xml 中缺少关键依赖
检查发现并不缺少依赖
- Maven 依赖未刷新 / 下载失败
多次刷新都导入依赖不成功
- 本地 Maven 仓库或配置问题
本地 Maven 仓库或配置没问题
排查了以上3个方向均没有问题,得不到解决
最后发现是在 IntelliJ IDEA 中配置 Maven 时出了问题

Bundled (Maven 3): 用 IDEA 内置 Maven,方便但版本可能受限,升级 IDEA 时易出兼容问题。
Use Maven wrapper: 按项目指定版本下载 Maven,保证构建一致,但若配置或网络有问题,可能无法下载。我的项目中没有正确配置 Maven Wrapper(比如配置文件缺失或版本号错误),导致无法下载指定版本的 Maven,进而无法进行项目构建。
自定义路径: 用本地安装的 Maven,灵活可控,路径错或版本不兼容会导致构建失败。
修改成Bundled (Maven 3),重新刷新maven,报错消失。
Spring的命名空间
一、总述

二、具体实验
2.1引入自定义命名空间
首先要加入要引入的东西的坐标(也就是pom文件中的依赖,以引入springmvc为例)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
其次是改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"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd“>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl2" autowire="byType">
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
</beans>
要引入mvc,只需要加三个地方(其实如果是Spring的组件的话都是类似的,可以复制粘贴,然后改不同的即可,不是Spring的组件就得自己去找命名空间及命名空间约束了)
命名空间
xmlns:mvc="http://www.springframework.org/schema/mvc"
命名空间、schane地址(jar包命名空间对应的虚拟地址,下面两个必须是成对的):
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
最后是这样:
<?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:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl2" autowire="byType">
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
</beans>
然后就可以引入mvc标签了:
<?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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
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
<mcv:annotation-driven/>
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl2" autowire="byType">
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
</beans>
2.2标签配置不同的环境
使用方式:
1、在配置文件中使用beans的profile属性来进行声明:
<beans profile="dev">
<!-- 再在环境里面像正常一样配置bean-->
<bean class="com.itheima.service.impl.UserServiceImpl2" id="userServiceImpl2"/>
</beans>
<!-- 再配置一个测试环境-->
<beans profile="test">
<bean class="com.itheima.dao.impl.UserDaoImpl" id="userDao"/>
</beans>
2、使用System.setProperty(“spring.profiles.active”,“环境名来进行调用”),例如:
System.setProperty("spring.profiles.active","test");
System.setProperty("spring.profiles.active","dev");
测试:
package com.itheima.test;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.service.UserService;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.xml.bind.annotation.XmlAccessOrder;
public class BeanFactoryTest {
public static void main(String[] args) {
System.setProperty("spring.profiles.active","test");
// 直接使用ApplicationContex来进行加载
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_beanfac.xml");
System.out.println(applicationContext.getBean("userDao1"));
}
}

### 2.3使用标签将子配置文件导入主配置文件中
使用方式:
1、在子配置文件中定义bean
applicationContextOrder.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.itheima.service.impl.UserServiceImpl"></bean>
</beans>
applicationContextUser.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"></bean>
</beans>
2、在主配置文件中使用标签
<?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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
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
<import resource="classpath:applicationContextOrder.xml"/>
<import resource="classpath:applicationContextUser.xml"/>
</beans>
测试及结果:
package com.itheima.test;
import com.itheima.dao.impl.UserDaoImpl;
import com.itheima.service.UserService;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.xml.bind.annotation.XmlAccessOrder;
public class BeanFactoryTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext_beanfac.xml");
System.out.println(applicationContext.getBean("userService"));
System.out.println(applicationContext.getBean("userDao"));
}
}

### 2.4使用标签进行取别名
但是使用name属性也可以,只不过 是一个单独的标签而已。
实验:
<bean class="com.itheima.dao.impl.UserDaoImpl" id="userDao" name="aaa,bbb"/>
<!-- 使用alias标签起别名-->
<alias name="userDao" alias="xxx"/>
<alias name="userDao" alias="yyy"/>
结果:







BeanFactory 与 ApplicationContext 的关系
一、总述
1、BeanFactory 是 Spring 的早期接口,称为 Spring 的 Bean 工厂,ApplicationContext 是后期更高级接口,称之为 Spring 容器;
2、ApplicationContext 在 BeanFactory 基础上对功能进行了扩展,例如:监听功能、国际化功能等。BeanFactory 的 API 更偏向底层,ApplicationContext 的 API 大多数是对这些底层 API 的封装;
3、Bean 创建的主要逻辑和功能都被封装在 BeanFactory 中,ApplicationContext 不仅继承了 BeanFactory,而且 ApplicationContext 内部还维护着 BeanFactory 的引用,所以,ApplicationContext 与 BeanFactory 既有继承关系,又有融合关系。
4、Bean 的初始化时机不同,原始 BeanFactory 是在首次调用 getBean 时才进行 Bean 的创建,而 ApplicationContext 则是配置文件加载,容器一创建就将 Bean 都实例化并初始化好。
二、论述
2.1第二、三点:
上图可以看出ApplicationContext 对 BeanFactory 有继承关系,同时也继承了ApplicationEventPublisher、MessageSource、ResourcePatternResolver分别对应事件发布与监听、国际化(i18n)与消息管理、资源路径解析与批量加载。

BeanFactory 与 ApplicationContext 的关系-CSDN博客
Spring BeanFactory版本
一、整体思想
通过工厂的方式获取Bean对象,那么就需要一份清单、读取清单的读取器(读取器要与工厂绑定)、工厂。其中所谓的清单就是xml配置文件。


浙公网安备 33010602011771号