JavaEE的知识记录

内容很多可以通过目录进行查找对应的内容。

目录

一、注解

元注解

@RequestMapping 路由映射注解

@RequestParam绑定请求参数到可控制器方法的参数

请求参数绑定可控制方法参数:

参数绑定重命名

@RequestBody请求正文注解

@ResponseBody响应体正文注解

@PathVariable 请求url路径中url的参数与方法参数的绑定

@RequestPart上传文件

@RestController 和@Controller

@Controller

@RestController

五大类注解和@Bean方法注解在下面有讲,可通过目录进行查找

@Autowired 注解

二、请求学习:

1.传递单个参数

2.传递多个参数

3.传递对象

4.传递数组

5.传递集合

6.传递JSON数据

7.从URL中获取参数

8.通过请求上传文件

9.获取Cookie/Session

获取Cookie

 获取Session

10.获取Header

 三、响应学习

1.返回静态页面

 2.返回数据@ResponseBody

3.返回HTML代码片段

 4.返回JSON

5.设置状态码

四、Spring IOC&DI

1.IOC(控制反转)的核心思想

什么是IOC?

IOC容器的核心作用

2.DI(依赖注入):IOC的具体实现技术

什么是依赖?

什么是依赖注入(DI)?

常见的依赖注入方式

三种注入优缺点分析:

 3.Spring框架中的核心概念:Bean注解

Bean是什么?

五大类注解和方法注解

类注解:标记Bean的角色

方法注解@Bean:定义Bean的创建逻辑

1)通过@Bean方法手动创建外部类的实例,将其注册为Spring Bean

2)定义多个对象的处理方法

通过重命名Bean或指定名称

Bean名和方法名一致

 使用@Primary注解标识默认对象

使用@Qualifier

使用@Resource注解标注名称注入对应名称的@Bean

补充:Bean的命名规则

扫描路径


 

一、注解

元注解

元注解的作用就是负责注解其他注解,在其他注解的源码中可以看到元注解。常见的元注解有以下几种:

  • @Retention:指定其所修饰的注解的保留策略。比如SOURCE值表示注解只在源文件中保留,编译期间删除;CLASS表示注解只在编译期间存在于.class文件中,运行时JVM不可获取注解信息。
  • @Document:该注解是一个标记注解,用于指示一个注解将被文档化。
  • @Target:用来限制注解的使用范围。值为Type表示可以修饰类,接口,注解或枚举类型;FIELD表示修饰属性;METHOD表示可以修饰方法。除了这些还有很多值。
  • @Inherited:该注解使父类的注解能被其子类继承。
  • @Repeatable:该注解是java8新增的注解,用于开发重复注解。

@RequestMapping 路由映射注解

这是一个用来处理请求“地址映射”的注解,可用于映射一个请求或一个方法,可以用在类和方法是上。

  • 标注在方法上:

用于方法上,表示在父路径下追加方法上注解中的地址将会访问到该方法

  • 标注在类上:

用于类上,表示类中的所有相应请求的方法都是以该地址作为父路径。

此外@RequestMapping支持get和post方法,所以在用该注解修饰方法时可以自己设置method属性:

@RequestMapping(value = "/sayhi/b",method = RequestMethod.GET)

@RequestParam绑定请求参数到可控制器方法的参数

请求参数绑定可控制方法参数:

@RequestMapping("/m6")
public String method2(@RequestParam List<String> list) {return list.toString();
}

使用该注解,可以自动将HTTP请求中的同名多值参数绑定到该集合,若省略该注解,Spring不会自动绑定多值请求参数到该集合中,这会导致list为null或绑定失败,所以必须显式的添加该注解

但是控制器方法的参数为数组类型时,即使不显式的使用该注解,Spring也会默认将HTTP请求中的同名多值参数自动绑定到该数组中,这是和其他集合类不一样的地方。

@RequestMapping("/m5")public String method( String[] arraryParam){return Arrays.toString(arraryParam);}

当然了,数组也可以显式的去添加该注解。

@RequestMapping("/m5")public String method(@RequestParam String[] arraryParam){return Arrays.toString(arraryParam);}

参数绑定重命名

某种情况下,前端传递的参数key和后端传送的参数key不一致,比如前端传递了一个time,而后端使用createtime来接收,这样后端就会出现参数收不到的情况,若出现这种情况,我们可以使用注解@RequestParam来重命名后端参数的值。

@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {return "接收到参数createtime:" + createtime;
}

上面的代码中,前端传递了time的值,然后传递给后端的createtime,这样就能够保证前端和后端参数定义可以不一致。

若前端利用createtime进行传递,浏览器就会报错;并且用了该注解,该参数必须进行传递。

当然,我们可以设置属性,让该参数变成不必传的参数,即使不传或者key参数错误,返回的value值都是null。

@RequestMapping("/m4")
public Object method_4(@RequestParam("time",require =false) String createtime) {return "接收到参数createtime:" + createtime;
}
  • 传递错误的key:

  • 不传递值:

@RequestBody请求正文注解

具体实现可以看 6. 传递JSON数据

意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中,即HTTP请求正文直接映射到方法的参数。

 @RequestMapping("/m7")public Object method3(@RequestBody User user){return user.toString();}

@ResponseBody响应体正文注解

@ResponseBody既是类注解又是方法注解。这个注解用在类上表示该类的所有方法返回的都是数据;若作用在方法上,表示该方法返回的是数据。

这个注解的作用是方法的返回值作为响应体进行返回。

   @ResponseBody@RequestMapping("/user")public String getUser() {return "index.html"; // 返回视图名称(如 user-page.jsp)}

@PathVariable 请求url路径中url的参数与方法参数的绑定

path variable:路径变量

这个注解主要作用在请求URL路径上的数据绑定

默认传递参数写在URL上,springMVC就可以通过数据绑定获取到该参数。

后端实现代码:

@RequestMapping("/m8/{id}/{name}")public String method4(@PathVariable Integer id, @PathVariable String name){return "解析参数id:"+id+",name:"+name;}

同时我们可以对后端参数进行重命名,让前端参数和后端参数映射。

@RequestMapping("/m8/{id}/{name}")public String method4(@PathVariable Integer id, @PathVariable("name") String username){return "解析参数id:"+id+",name:"+username;}

 @RequestPart上传文件

是springmvc中用于处理多部分请求的注解,常用于文件上传、同时传递文件和其他结构化数据。

核心作用:

  • 处理文件上传:绑定请求中的文件部分到MultipartFile类型的参数
  • 结构化数据:解析请求中的非文件部分到java对象,通常结合@RequestBody使用。
  • 支持复杂请求:适用于需要同时上传文件和其他元数据的场景(上传用户头像并附带用户信息)。
@RequestMapping("/m9")public String getFile(@RequestPart("file") MultipartFile file) throws IOException {//获取文件名称String filename = file.getOriginalFilename();//文件上传到指定路径file.transferTo(new File("D:/Postman/"+filename));return "接收到的文件名称为"+filename;}

 使用postman发送请求:

@RestController 和@Controller

这两个注解有本质的区别,导致两者在返回结果时表现不同。

@Controller

本质是传统的Spring MVC控制器,Spring框架启动时加载,把这个对象交给Spring进行管理。

用法:用于处理客户端发起的请求,并负责返回适当的视图(view)作为响应,即方法默认返回视图名称(需配合视图解析器解析为HTML/JSP等页面)。

 @RequestMapping("/user")public String getUser() {return "/index.html"; // 返回视图名称(如 user-page.jsp)}

页面展示结果:

 其中,项目文件中要有对应的视图文件(index.html),若没有会返回404错误;并且该方法的类是引用@Controller这个注解的。

@RestController

本质是@Controller和@ResponseBody的组合注解。

用法:在使用@RestController注解标记的类中,每个方法的返回值都会以JSON或xml的形式直接写入HTTP响应体中,即所有方法默认返回数据(如JSON、xml),而非视图名称。

@RequestMapping("/user")public String getUser() {return "/index.html"; // 返回视图名称(如 user-page.jsp)}

 其中该代码使用了@RestController注解,访问页面中会显示/index.html。

五大类注解和@Bean方法注解在下面有讲,可通过目录进行查找

@Autowired 注解

需要搭配类级别的Spring管理注解使用,因为它的核心机制依赖于Spring容器来管理Bean的创建和依赖注入,所以被@Autowired注入的类必须被Spring容器管理。


二、请求学习:

请求的学习主要是学习如何传递参数

1.传递单个参数

2.传递多个参数

参数如果使用基本数据类型必须要传递值,不传递就会报错,所以开发时建议使用包装类型

3.传递对象

如果有很多形参时,就要传递很多参数,并且后续每增加一个参数,也需要修改方法声明,那么我们可以把这些参数封装成一个对象。

这样我们可以通过URL填写参数值,queryString的参数key与类型值要与后端的属性名要一致 ,如果属性类型是包装类型,queryString参数key和后端属性名不一致的话,返回的结果是null,若属性是基本类型,querystring参数key和后端参数的名不一致的话,返回就会报错。

4.传递数组

当请求参数名与形参数组名称相同且请求参数为多个,后端定义数组类型形参即可接收参数。

   @RequestMapping("/m5")public String method(String[] arraryParam){return Arrays.toString(arraryParam);}

其中url还可以为:

http://127.0.0.1:8080/s/m5?arraryParam=zhangsan&arraryParam=lisi

或者http://127.0.0.1:8080/s/m5?arraryParam=zhangsan%2clisi%2cwangwu

5.传递集合

集合参数:和数组类似,同一个请求参数名有多个,且需要使用@RequestParam绑定参数关系。

默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系。

其中url的请求方式和数组类似。

@RequestMapping("/m6")public String method2(@RequestParam List<String> list){return list.toString();}

6.传递JSON数据

JSON概念:JavaScript Object Notation,即JavaScript对象表示法。

JSON是一种轻量级的数据交互格式,它基于ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。

简单来说:JSON就是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,因此JSON本质是字符串。主要负责在不同语言中数据传递和交换。

JSON和JavaScript的关系:

两者没有关系,只是语法相似,js开发者能更快的上手而已,但是他的语法本身比较简单,所以很好学。

JSON的语法:

  1. 数据在键值对(key/value)中
  2. 数据由逗号,分割
  3. 对象用{}表示
  4. 数组用[ ]表示
  5. 值可以为对象,也可以为数组,数组中可以包含多个对象。

下面可以看一段JSON数据:

{"squadName": "Super hero squad","homeTown": "Metro City","formed": 2016,"secretBase": "Super tower","active": true,"members": [{"name": "Molecule Man","age": 29,"secretIdentity": "Dan Jukes","powers": ["Radiation resistance", "Turning tiny", "Radiation 
blast"]}, {"name": "Madame Uppercut","age": 39,"secretIdentity": "Jane Wilson","powers": ["Million tonne punch", "Damage resistance", "Superhuman 
reflexes"]}, {"name": "Eternal Flame","age": 1000000,"secretIdentity": "Unknown","powers": ["Immortality", "Heat Immunity", "Inferno", 
"Teleportation", "Interdimensional travel"]}]
}

JSON的两种结构:

对象:用大括号{}保存的对象是一个无序的键值对集合,一个对象以左括号{开始,右括号}结束。每个键后跟一个冒号:,键值对使用逗号,分隔。

数组:中括号 [ ] 保存的数组是值(value)的有序集合。一个数组以左中括号[开始,右中括号]结束,值之间使用逗号,分隔。

JSON和java对象互转

JSON本质上是一个字符串,通过文本来存储和描述数据

SpringMVC框架也集成了JSON转换工具,我们可以直接使用来完成JSON字符串和java对象的互转。

springmvc已经把转换的依赖引进来了,所以不用再去官网上去找依赖并引进去。

JSON优点:

简单易用;跨语言支持;轻量级,占用宽带小;易于扩展,支持嵌套对象和数组;安全性好,JSON格式是一种纯文本格式不会执行恶意代码。

 传递JSON对象:

接收JSON对象需要使用@RequestBody注解。

RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中(body)。

后端实现:

 @RequestMapping("/m7")public Object method3(@RequestBody User user){return user.toString();}

利用postman来发送JSON请求参数:

响应结果:

7.从URL中获取参数

从URL获取参数是利用注解@PathVariable

@RequestMapping("/m8/{id}/{name}")public String method4(@PathVariable Integer id, @PathVariable("name") String username){return "解析参数id:"+id+",name:"+username;}

8.通过请求上传文件

后端实现:
 

@RequestMapping("/m9")public String getFile(@RequestPart("file") MultipartFile file) throws IOException {//获取文件名称String filename = file.getOriginalFilename();//文件上传到指定路径file.transferTo(new File("D:/Postman/"+filename));return "接收到的文件名称为"+filename;}

9.获取Cookie/Session

关于cookie和session的内容可以看这篇博客:session和cookie

获取Cookie

由于Spring MVC是基于Servlet API构建的原始Web框架,也是在Servlet的基础上实现的。

所以我们可以更简单的获取Cookie。

  @RequestMapping("/getcookie")public String cookie(@CookieValue("bite") String bite){return "bite:"+bite;}

利用@CookieValue这个注解让参数“bite”与浏览器中的名称bite进行绑定然后获取对应的value值。

 获取Session

通过Spring MVC内置对象HttpSession来获取。

  @RequestMapping("/getSession")public String getSession(HttpSession session){session.setAttribute("name","java");String name = (String)session.getAttribute("name");return "name:"+name;}

Session不存在的情况下,创建session对象并存储信息。

 此时创建session对象,服务器会返回携带有sessionID的cookie并存储到浏览器中。

10.获取Header

通过Spring MVC框架简洁获取Header。

 @RequestMapping("/header")public String header(@RequestHeader("User-Agent") String userAgent){return "userAgent" + userAgent;}

@RequestHeader注解的参数值为HTTP请求报头中的“Key”


 三、响应学习

http响应结果可以是数据,也可以是静态页面内,也可以针对响应设置状态码,Header信息等。

1.返回静态页面

创建前端页面index.html

 html代码如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Index⻚⾯</title>
</head>
<body>Hello,Spring MVC,我是Index⻚⾯.
</body>
</html>

后端代码:

//类路径为 /s
@RestController
public class IndexController {@RequestMapping("/index")public Object index(){//返回index.htmlreturn "/index.html";}
}

输入:http://127.0.0.1:8080/s/index

得到的结果为:

 结果发现,页面未能正确返回,http响应把“/index.html”当做了http响应正文的数据。为了让springmvc能识别出index.html是一个静态页面并返回响应,我们把@RestController改为@Controller即可:

@Controller
public class IndexController {@RequestMapping("/index")public Object index(){return "/index.html";}
}

再次输入刚刚的url即可访问该静态页面:

 2.返回数据@ResponseBody

该注解是把返回的数据通过响应体进行返回。

由于@RestController是@Controller和@ResponseBody的结合,那么我们可以这样子:

@Controller
public class IndexController {@RequestMapping("/index")public Object index(){return "/index.html";}@RequestMapping("/returnData")@ResponseBodypublic String returnData(){return "该⽅法返回数据";}
}

再次运行程序,浏览器响应结果为:

若去掉@ResponseBody,程序会报404错误。

@Controller
public class IndexController {@RequestMapping("/index")public Object index(){return "/index.html";}@RequestMapping("/returnData")@ResponseBodypublic String returnData(){return "该⽅法返回数据";}
}

程序中就只剩下了@Controller,程序就会认为返回的是视图,根据内容去查找文件,但是查询不到,路径不在,报404.。

3.返回HTML代码片段

若后端返回数据时,如果数据中有HTML代码,也会被浏览器解析。

@RequestMapping("/returnHtml")
@ResponseBody
public String returnHtml() {return "<h1>Hello,HTML~</h1>";
}

响应体(body)的类型(Content-Type)为text/html。

 如果返回的代码片段是js,SpringMVC会自动设置Content-Type 为 application/javascript。

如果请求的是css⽂件, Spring MVC会⾃动设置Content-Type为 text/css。

 但是要配合上@Controller注解以及要有js文件和css文件。

@RequestMapping("/index2")public Object index2(){return "/a.js";}@RequestMapping("/index3")public Object index3(){return "/b.css";}

抓包结果:

 4.返回JSON

当方法返回的是对象时,content-type自动设置为application/json。

 @RequestMapping("returnJson")public User returnJson(User user){return user;}

 可以看到,返回的响应体为JSON格式的。

5.设置状态码

springmvc会根据我们方法的返回结果自动设置响应状态码,当然我们也可以手动指定状态码,通过springmvc的内置对象 HttpServletResponse 提供的方法来进行设置。


四、Spring IOC&DI

1.IOC(控制反转)的核心思想

什么是IOC?

IOC(Inversion of Control)是一种设计原则,其核心思想是将对象的创建、依赖管理和生命周期的控制权交给一个容器(IOC容器),而不是由对象自身直接控制。

  • 传统方式:对象主动创建和管理依赖(如new UserService() ),导致类之间高度耦合。
  • IOC方式:由容器统一创建和管理对象,对象只需声明需要哪些依赖,容器负责注入到类中。      

IOC容器的核心作用

创建对象:根据配置或注解,实例化类并管理其生命周期。

管理依赖关系:自动处理对象之间的依赖(如A类需要B类的实例)。

2.DI(依赖注入):IOC的具体实现技术

什么是依赖?

如果一个类需要另一个类的实例才能完成功能,则称其依赖这个类。

例如:底盘依赖于车身,底盘是依赖方,车身是被依赖方,看下面的代码中,需要把底盘这个依赖注入到车身的类中。

这是控制反转的一个简单的例子。

什么是依赖注入(DI)?

DI(Dependecy Injection)是实现IOC的具体技术,通过将依赖对象的实例从外部(IOC容器)注入到目标对象中,而非由目标对象自己创建。

  • 核心思想:对象的依赖关系由外部提供,而不是内部硬编码。
  • 关键角色:IOC容器负责创建依赖对象并注入到需要的位置。

常见的依赖注入方式

方式描述
构造器注入通过构造函数传递依赖对象
Setter注入通过Setter方法设置依赖对象
属性注入直接通过字段(属性)的方式注入依赖
三种注入优缺点分析:
  • 属性注入:

属性注入的流程如下:

1.实例化对象,先调用类的默认无参构造器创建对象。

2.反射注入字段:通过反射机制直接对字段赋值。

优点

简洁,使用方便。

缺点

只用用于IOC容器,如果非IOC容器就不可以了,并且只有在使用的时候才会出现NPE(空指针异常)。

不能注入一个Final属性。

理由:Final字段必须在构造期间完成初始化,但是属性注入是在对象构造完后通过反射赋值,根据依赖注入的流程,无法满足final的要求。

@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}@Controller
public class UserController {//注⼊⽅法1: 属性注⼊@Autowiredprivate UserService userService;public void sayHi(){System.out.println("hi,UserController...");userService.sayHi();}
}

若把 @Autowired注解去掉,就会报出空指针异常,spring不会自动创建该实例并进行赋值,因此,userService属性保持null值。

  • 构造函数注入:

构造器注入流程如下:

  1. 实例化对象:Spring直接调用有参构造器创建对象,不需要默认无参构造器。
  2. 注入依赖:依赖参数在构造器调用你时直接传入(无需后续反射赋值)。

优点:

可以注入final修饰的属性,注入的对象不会被修改,满足final的要求。

依赖对象在使用前一定会被完全初始化,因为依赖是在类的构造方法中执行的,而构造方法是在类加载阶段就会执行的。

通用性好,构造方法是JDK支持是、的,所以更换任何框架,他都是适用的。

缺点:

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

@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}public class UserController {private final UserService userService;@Autowired// 构造器注入:依赖字段是 final 的public UserController(UserService userService) {this.userService = userService;}
}

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

  • Setter注入:

Setter依赖注入流程:

  1. 实例化对象:调用默认无参构造器创建对象。
  2. 反射调用setter方法:通过反射调用Setter方法注入依赖。

优点:

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

缺点:

不能注入一个Final修饰的属性。

注入对象可能会被改变,因为setter方法可能会被多次调用,就有被修改的风险。

@Service
public class UserService {public void sayHi() {System.out.println("Hi,UserService");}
}@Controller
public class UserController3 {//注⼊⽅法3: Setter⽅法注⼊private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}
}
若把@Autowired注解去掉,同属性注入一样,spring默认不会自动调用setter方法进行注入,因此 userService 字段会保持 null,后续调用的方法userService.sayHi() 时抛出空指针异常。

 3.Spring框架中的核心概念:Bean注解

Bean是什么?

定义:由spring IOC容器管理的对象称为Bean。

生命周期:Bean的创建、初始化、依赖注入和销毁均为容器控制。

五大类注解和方法注解

类注解:标记Bean的角色

Spring通过注解标记类,告诉容器哪些类需要被管理为Bean,并明确角色:

注解用途
@Component通过注解,标记任意类为Bean
@Controller标记为Web控制器(处理HTTP请求)
@Service标记业务逻辑层组件
@Repository标记为数据访问层组件(DAO)(自动处理数据库异常转换)
@Configuration标记为配置类(定义Bean的创建方式,常与@Bean配合使用)

 在Spring中,五大核心注解虽然最终都能将类注册为Spring Bean ,但它们设计的目的是为了区分代码的分层和职责,比如要在业务逻辑层使用@Component或@Service,很显然@Service是更好的选择。此外,这些注解还在功能上存在细微的差异,并非完全一样

差异体现:

注解特殊行为
@Component无特殊行为
@Controller@Controller注解的类通常与@RequestMapping,@GetMapping等注解配合使用,处理HTTP请求。
@Service无特殊行为,但强调业务逻辑的封装
@Repository自动转换数据访问异常为Spring异常
@Configuration标记类为配置类,配合@Bean使用

我们可以查看注解源码:

 可以看到,这些注解里面都有一个注解@Component,说明它们本身就是属于@Component的“子类”。这些注解被称为@Component的衍生注解。

方法注解@Bean:定义Bean的创建逻辑

@Bean 核心功能:

在Spring配置类中,通过@Bean注解的方法手动显式的创建对象,并将对象交给Spring 容器管理(成为Spring Bean)。

注解用途
@Bean在配置类中标注方法,表示该方法返回一个Bean(用于定义第三方库组件的创建方式)

 @Bean方法注解要搭配类注解进行使用。

@Configuration
public class AppConfig {@Beanpublic UserRepository userRepository() {return new UserRepositoryImpl();}
}

 补充:无论目标类是否有Spring注解,只要通过@Bean方法返回其实例,Spring就会管理该对象。比如上面的代码中,尽管UserRepository类没有被@Component这样的注解所标记,但是仍然能通过@Bean方法注册,Spring会直接使用该方法返回的实例。

但是目标类同时有@Component和@Bean时,Spring就会通过注解@Component扫描和@Bean方法注册,Spring就会报错,

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

  • 1.当使用第三方库或外部依赖包中的类时,是无法直接修改其源码添加Spring注解(如@Component);
  • 2.一个类,需要多个对象,比如多个数据源。

像这种场景,就需要可以使用方法注解@Bean来解决了

1)通过@Bean方法手动创建外部类的实例,将其注册为Spring Bean
@Configuration
public class ExternalConfig {// 将外部类 Gson 注册为 Bean@Beanpublic Gson gson() {return new Gson(); // 手动创建实例}
}

在配置类中,通过@Bean来获得外部依赖类的实例。

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

@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可以针对同一个类,定义多个对象。

下面是解决同一类型中有多个对象时的解决方法:

通过重命名Bean或指定名称

可以通过设置name属性给Bean对象进行重命名操作:

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

此时我们可以使用重命名后的u1这个名称来获得Bean对象了。

User u1 = (User) context.getBean("u1");

当然,name={}可以省略,如下:

@Bean({"u1","user1"})

只有一个名称时,{}也是可以省略的。

@Bean("u1")
Bean名和方法名一致

以下是完整代码:

@Configuration
public class A {@Beanpublic User User1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic User User2(){User user = new User();user.setName("zhangsi");user.setAge(10);return user;}}@Data
public class User {private String name;private Integer age;
}@SpringBootApplication
public class Demo14Application {public static void main(String[] args) {ApplicationContext context = SpringApplication.run(Demo14Application.class, args);User user1 = (User) context.getBean("User1");User user2 = (User) context.getBean("User2");System.out.println(user1);System.out.println(user2);}}

运行结果:

 使用@Primary注解标识默认对象
    @Primary@Beanpublic User User1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}

使用@Primary注解,表示让Spring默认匹配该对象。

使用@Qualifier

使用@Qualifier注解:指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean的名称。

比如在属性注入中@Qualifier注解不能单独使用,必须配合@Autowired使用。

   @Qualifier("User1")@Autowiredprivate User user1;

属性注入中指定了对应的Bean对象(即有方法返回对应名称(User1)的Bean对象,没有会报错)。

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

代码解读:注入了指定名称的User1的Bean对象。

使用@Resource注解标注名称注入对应名称的@Bean

使用方法:

@Resource(name = "User1")private User user1;

@Resource这个注解和@Autowire有点像,但是还是有区别的。

@Autowire和@Resource的区别:

  • @Autowire是Spring框架提供的注解,而@Resource是JDK提供的注解。
  • @Autowire默认是按照类型注入,而@Resource是按照名称注入,相比于@Autowire来说,@Resource支持更多的参数设置,例如根据Bean的name来获得想要的Bean。
补充:Bean的命名规则

1)五大注解存储的bean

  1. 前两位字母均为大写,bean名称为类名,比如SEvice类,bean的名称就为 SEvice。
  2. 其他的类为类名首字母小写,比如Service,bean的名称为service;service,bean的名称为service。
  3. 可以通过value属性设置@Controller(value="user")

2)@Bean注解存储的bean

  1. bean名称为方法名。
  2. 通过name属性设置@Bean(name={"u1","user1"})。

扫描路径

使用前面的学习的类注解去声明bean,一定会生效吗?

不一定!!

默认的的扫描范围是Springboot启动类所在的包里面。

如果不在启动类所在的包里面可以在配置类上添加@ComponentScan注解,该注解默认会扫描该类所在包下的所有的配置类。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带旋转的目标标注工具-X-AnyLabeling

在之前的文章中&#xff0c; 分别介绍过3款标注工具&#xff1a; 目标检测&#xff0c;语义分割标注工具–labelimg labelme智能标注工具 T-Rex Label 对于2D目标检测标注&#xff0c; 上面的工具只能标注不带旋转的检测框。但是如果我们要进行带旋转方向的检测&#xff08;O…

Javascript基础

目录 1. 变量声明2. 基本数据类型3.复杂数据类型4.字符串方法5.对象方法6.时间方法7.条件&#xff08;if&#xff09;8.循环&#xff08;for/while&#xff09;9.遍历&#xff08;for in/of&#xff09;10.多选&#xff08;Switch&#xff09;END 1. 变量声明 const&#xff1…

设计模式之建造者模式

目录 1. 概念 2. 代码实现 3. 应用场景 建造者模式(Builder)是创建型设计模式的最后一个&#xff0c;但是确实在平时开发过程中或者阅读源码过程中是十分常见的&#xff0c;难度在我来看是比较适中的&#xff0c;理解起来的也比较轻松&#xff0c;并且平时我们在编码过程中也…

【NeurIPS-2022】CodeFormer: 将人脸复原转化为码本预测以减少LQ-HQ映射的不确定性

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文动机方法实验 总结互动致谢参考往期回顾 前言 盲人脸恢复是一个高度不适定的…

JAVA-多线程join()等待一个线程

引言&#xff1a;更多线程的认识可以看一篇博客&#xff1a; JAVA-Thread类实现多线程-CSDN博客 一、join()的作用 我们知道线程是随机调度执行的&#xff0c;但是有时候我们需要另一个任务完成了&#xff0c;我们才能继续&#xff0c;这个时候我们就可以使用join去等待线程结束…

《AI大模型开发笔记》——企业RAG技术实战

RAG(Retrieval-Augmented Generation)介绍 Retrieval-Augmented Generation for Large Language Models: A Survey: https://arxiv.org/abs/2312.10997 github项目: https://github.com/Tongji-KGLLM/RAG-Survey RAGFlow项目 ragflow项目地址: https://github.com/inf…

蓝桥杯备考:特殊01背包问题——》集合subset

我们划分成两个集合&#xff0c;实际上我们只需要看一部分就行了&#xff0c;也就是从集合的所有元素里挑出恰好满足集合总和的一半儿&#xff0c;当然&#xff0c;如果我们的集合总和是奇数的话&#xff0c;我们是无论如何也挑不出刚好一半儿的&#xff0c;因为我们没有小数&a…

python字符级差异分析并生成 Word 报告 自然语言处理断句

import difflib from docx import Document from docx.shared import RGBColor from snownlp import SnowNLPdef analyze_char_differences(text_a, text_b):"""分析两个文本的字符级差异:param text_a: 第一个文本:param text_b: 第二个文本"""…

尝试在软考66天前开始成为软件设计师-数据库系统

三级模式-两级映射 层次型架构设计 ---便利,应变能力↗ 外模式 (用户与数据库系统的接口 视图概念模式 (数据库中全体数据的逻辑结构和特征内模式 (数据物理结构和存储方式 外模式/模式映像。 该映像存在于外部级和概念级之间&#xff0c;实现了外模式到概念模式…

Hadoop•常用命令

听说这是目录哦 操作命令&#x1f96f;退出清屏切换工作目录移动文件查看创建删除复制文件内容查看编辑解压缩其它命令技巧 系统命令&#x1f355;vim操作命令(命令模式下)光标移动复制粘贴(vi编辑器内部)删除、撤销 若vi&#xff0c;vim&#xff0c;ls找不到命令⚠️能量站&am…

linux之 内存管理(1)-armv8 内核启动页表建立过程

一、内核启动时&#xff0c;页表映射有哪些&#xff1f; Linux初始化过程&#xff0c;会依次建立如下页表映射&#xff1a; 1.恒等映射&#xff1a;页表基地址idmap_pg_dir; 2.粗粒度内核镜像映射&#xff1a;页表基地址init_pg_dir; 3.fixmap映射&#xff1a;页表基地址为…

IntelliJ IDEA 快捷键系列:重命名快捷键详解

目录 引言一、默认重命名快捷键1. Windows 系统‌2. Mac 系统‌ 二、操作步骤与技巧1. 精准选择重命名范围‌2. 智能过滤无关内容‌ 三、总结 引言 在代码重构中&#xff0c;‌重命名变量、类、方法‌ 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 ‌Ma…

Swagger-告别手写文档

文章目录 1. 引言2. Swagger是什么&#xff1f;3. SpringBoot2.7.3集成Swagger4. 常见注解 1. 引言 在RESTful API开发中&#xff0c;维护准确、易读的接口文档是团队协作的核心挑战&#xff0c;通常接口文档分为离线的和实时的。离线的接口文档工具有 YAPI等&#xff0c;其中…

深入解析 C++ Vector:全面掌握 STL 核心容器的原理与高效实践

一、Vector 的核心概念与特性 Vector 是 C 标准库中最常用的动态数组容器&#xff0c;其底层基于连续内存存储元素&#xff0c;兼具数组的高效访问与动态扩容的灵活性。以下是其核心特性&#xff1a; 1.1 核心特性对比 特性普通数组Vector 容器内存分配静态固定动态增长访问效…

element-plus中DatePicker 日期选择器组件的使用

1.选择某一天 代码&#xff1a; <el-date-pickerv-model"invoice_date"type"date"placeholder"请选择日期"style"width: 200px;"clearable /> 运行效果&#xff1a; 问题所在&#xff1a;这个数据的格式不是我们后端需要的那种&…

Python Bug修复案例分析:Python 中常见的 IndentationError 错误 bug 的修复

在 Python 编程的世界里&#xff0c;代码的可读性和规范性至关重要。Python 通过强制使用缩进来表示代码块的层次结构&#xff0c;这一独特的设计理念使得代码更加清晰易读。然而&#xff0c;正是这种对缩进的严格要求&#xff0c;导致开发者在编写代码时&#xff0c;稍有不慎就…

Deal - DbC、检查Python 值、异常和副作用

文章目录 一、关于 Deal特点 二、安装三、30秒内使用 Deal四、其它贡献 一、关于 Deal Deal 是用于 design by contract (DbC) 和 检查值、异常和副作用的Python库。简而言之&#xff0c;交易使您能够编写bug的代码。 通过在代码中添加一些装饰器&#xff0c;您可以获得免费测…

Linux 一步部署DHCP服务

#!/bin/bash #脚本作者和日期 #author: PEI #date: 20250319 #检查root权限 if [ "$USER" ! "root" ]; then echo "错误&#xff1a;非root用户&#xff0c;权限不足&#xff01;" exit 0 fi #防火墙与高级权限 systemctl stop firewa…

MyBatis操纵数据库-XML实现(补充)

目录 一.多表查询二.MyBatis参数赋值(#{ }和${ })2.1 #{ }和${ }的使用2.2 #{ }和${ }的区别2.3 SQL注入2.3 ${ }的应用场景2.3.1 排序功能2.3.2 like查询 一.多表查询 多表查询的操作和单表查询基本相同&#xff0c;只需改变一下SQL语句&#xff0c;同时也要在实体类中创建出…

【Java篇】一气化三清:类的实例化与封装的智慧之道

文章目录 类和对象&#xff08;中&#xff09;五、对象的构造及初始化5.1 如何初始化对象5.2 构造方法5.2.1 构造方法的概念5.2.2 构造方法的特性 5.3 默认初始化5.4 就地初始化 六、封装6.1 封装的概念6.2 访问限定符6.3 封装扩展之包6.3.1 包的概念6.3.3导入包6.3.3全类名6.3…