【Java Spring】SpringBoot Bean详解

文章目录

    • 1、@Bean方法注解简介
    • 2、@Bean注解重命名
    • 3、对象装配(获取Bean对象)
      • 3.1 对象装配之属性注入
      • 3.2 对象装配之Set 注入
      • 3.3 对象装配之构造方法注入
    • 4、@Resource VS @Autowired
    • 5、Bean对象的作用域
      • 5.1 验证Bean对象的默认作用域
      • 5.2 Bean对象的六大作用域详解
      • 5.3 @Scope注解设置Bean对象作用域
    • 6、Spring执行流程
    • 7、Bean生命周期

1、@Bean方法注解简介

上一节我们介绍了五大类注解,这一节介绍方法注解@Bean,@Bean作用的对象是方法,该注解需要搭配五大类注解同时进行使用,因为类方法的数量远远大于类的数量,如果使用@Bean注解标记方法的类没有被标记,那么Spring Boot项目在启动时需要遍历所有的类的所有方法,开销无疑是巨大的,但如果只遍历用五大类注解标记的类的方法,无疑大大减小了遍历范围

2、@Bean注解重命名

@Bean 类注解默认情况下,Bean name = 方法名,但是方法名是非常容易重复的,很可能在两个类中有两个相同的方法,它们通过方法类注解返回同一个类的对象,若这两个对象内部属性不相同,则可能出现误调的情况(本想调用A类的student方法返回名为张三的学生的,结果调用成B类的student方法返回了一个名为李四的学生)

并且这种错误并不会引起报错,一旦出现错误非常难以排查问题,而针对上述问题可以通过给@Bean设置name属性获取对象

@Controller
public class StudentBeans {@Bean(name = {"s1", "s2"})public Student student() {// 伪代码构建对象Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge(18);return stu;}
}

注:当给一个@Bean设置了name属性后,就无法使用方法名获取Bean对象了,只能通过设置的名称获取

3、对象装配(获取Bean对象)

获取Bean对象也叫做对象装配,就是把注入到Spring Boot中的某个对象取出来取出来放到指定类中,这种方法也叫做对象注入,对象装配的方法有三种,接下来将详细介绍

3.1 对象装配之属性注入

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

  • 优点:使用简单
  • 缺点:
    • 1、功能性问题: 无法注入一个不可变对象(final对象)
    • 2、通用型问题:只能适应于IoC容器
    • 3、设计原则问题:更容易违背单一设计原则

属性注入实例: 将StudentService对象注入到StudentController类中

package com.demo.controller;import com.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;@Controller
public class StudentController {@Autowiredprivate StudentService studentService;public void sayHi() {studentService.sayHi();}
}
package com.demo.service;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;@Service
public class StudentService {public void sayHi() {System.out.println("StudentService sayHi");}
}

接下来来介绍属性注入的缺点:

1、功能性问题:无法注入final对象。首先这个应该是jdk的问题而并非spring的问题,final修饰的变量不可被改变,一旦获取了初始值就不能重新被赋值,如果在类中使用final属性的成员,要么直接赋值,要么在构造函数中赋值

 private StudentService studentService; // 添加final关键字,无法赋值private final int number;   			// 报错:必须要直接进行赋值,或者写一个构造函数,在构造函数中赋值 

2、通用性问题:只能适用于IoC容器

3、设计原则问题:更容易违背单一设计原则

3.2 对象装配之Set 注入

完全符合单一设计原则,每一个Setter方法只针对一个对象,但是它的缺点也很明显,不能注入不可变对象,注入的对象可以被任意修改

使用方法:

  // 2、Setter注入private StudentService studentService;@Autowiredpublic void setStudentService(StudentService studentService) {this.studentService = studentService;}

3.3 对象装配之构造方法注入

Spring Boot 官方推荐的用法,如果当前类中只有一个构造方法,那么@Autowired注解可以省略
基本使用方法

// 3、构造方法注入private StudentService studentService;public StudentController(StudentService studentService) {this.studentService = studentService;}

构造方法注入的优点

1.可注入不可变对象,不可变对象可以在构造函数中初始化
2.注入对象不会被修改:构造方法在对象创建时只会执行一次,因此它不存在注入对象被随时(调用)修改的情况
3.注入对象会被完全初始化
4.通用性更好:构造方法注入可适用于任何环境,无论是 IoC 框架还是非 IoC 框架,构造方法注入的代码都是通用的,所以它的通用性更好。

4、@Resource VS @Autowired

功能:两者都是用来实现依赖注入的,功能非常相近

@Resource 和 @Autowired 的区别

  • 出身不同:@Autowired来自于Spring,而@Resource来自于JDK的注解
  • 使用时设置的参数不同:相比于@Autowired来说,@Resource支持更多的参数设置,例如name设置,根据名称获取Bean
  • @Autowired可以用于Setter注入,构造函数注入属性注入,而@Resource只能用于Setter注入和属性注入,不能用于构造函数注入

由于@Autowired支持的参数设置很少,所以产生了@Qualifier注解来扩充@Autowired 组件的功能

场景:使用@Bean注解向Spring中注入两个Student对象,当我们想要从Spring中取出对象,注入到其他对象中时,Spring就会不确定到底使用哪一个对象

package com.demo.componect;
import com.demo.model.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;@Controller
public class StudentBeans {@Bean(name = {"s1", "s2"})public Student student1() {// 伪代码构建对象Student stu = new Student();stu.setId(1);stu.setName("张三");stu.setAge(18);return stu;}@Beanpublic Student student2() {Student stu = new Student();stu.setId(2);stu.setName("李四");stu.setAge(20);return stu;}
}

@Resource 解决方式:

可以根据@Bean注解时设置的名称,来确定应该调用哪个@Bean注解标记的方法来获取指定对象

 	  @Resource(name = "s1")private Student student;

@Autowired 解决方式:

  • 可以根据 注入方法名 = 对象名称的方式来获取对象(不推荐)

     @Autowiredprivate Student student2;	
    
  • 使用@Qualifier注解可以对获取对象的方法进行筛选

        @Autowired@Qualifier("student2")private Student student;
    

5、Bean对象的作用域

作用域是Bean对象在整个Spring框架(项目)中的某种行为模式,Bean对象默认情况下是单例状态(singleton),也就是所有人使用的都是同一个Bean对象,所以Spring中的Bean的作用域默认也是单例模式(singleton)

5.1 验证Bean对象的默认作用域

示例:

@Controller
public class UserController {@Autowiredprivate User user1;public void getUser() {System.out.println("User1:" + user1);User u = user1;u.setName("李四");System.out.println("u:" + u);}
}
@Controller
public class UserAdviceController {@Resourceprivate User user1;public void getUser() {System.out.println("王五 | user1: " + user1);}
UserController uc = context.getBean("userController", UserController.class);uc.getUser();UserAdviceController ua = context.getBean("userAdviceController", UserAdviceController.class);ua.getUser();
输出:
User1:User(id=1, name=张三, password=15157722660)
u:User(id=1, name=李四, password=15157722660)
王武 | user1: User(id=1, name=李四, password=15157722660)

可以看到不管是通过创建局部变量,还是重新装配,获取到的都是同一个Bean对象,这说明Bean对象全局只有一份,这个对象是一个单例

5.2 Bean对象的六大作用域详解

Spring容器在初始化Bean实例时,同时会指定该实例的作用域,Spring有6种作用域,最后四种是基于Spring MVC生效的:

  • 1、singleton : 单例作用域(Spring默认选择该作用域),IOC容器中只存在一个实例
    • 使用场景:通常无状态Bean使用 该作用域,即Bean对象的属性状态无需更新(对象不会被改变)
  • 2、prototype : 原型作用域(多例作用域),每次对该作用域下的Bean的请求都会创建新的实例
    • 使用场景:通常有状态的Bean使用该作用域
  • 3、request:请求作用域,每次Http请求会创建新的Bean实例,类似于prototype
    • 使用场景:一次http的请求和响应的共享Bean(限定SpringMVC中使用)
  • 4、session:会话作用域,在一个http session中,定义一个Bean实例
    • 使用场景:用户回话的共享Bean,比如:记录一个用户的登录信息(限定SpringMVC种使用)
  • 5、application:全局作用域,在一个http servlet Context中,定义一个Bean实例。即一个context对象使用getBean获取类得到的是同一个实例
    • 使用场景:Web应用的上下文信息,比如:记录一个应用的共享信息(限定SpringMVC中使用)
  • 6、websocket:在一个HTTP WebSocket的生命周期中,定义一个Bean实例
    • 使用场景:WebSocket的每次会话中,保存一个Map结构的头信息,包裹客户端消息头。第一次初始化后,直到WebSocket结束都是用的同一个Bean(限定Spring WebSocket中使用 )

单例作用域(singleton) vs 全局作用域(application)

  • singleton是Spring Core的作用域; application 是Spring Web中的作用域
  • singleton作用域IoC容器,而application作用域Servlet容器

5.3 @Scope注解设置Bean对象作用域

@Scope标签可以用来声明Bean的作用域,比如设置Bean的作用域,如下代码所示:

@Data
@Controller
public class UserBeans {// 方法1:// @Scope("prototype")// 方法2:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Beanpublic User user1() {User user = new User();user.setName("张三");user.setId(1);user.setPassword("15157722660");return user;}
}

6、Spring执行流程

在这里插入图片描述

7、Bean生命周期

所谓生命周期指的是一个对象从诞生到销毁的整个生命过程,我们将这一过程叫做一个Bean对象的生命周期

  • 实例化Bean,将字节码转换成内存中的对象(即加载,为Bean分配内存空间)

  • 设置属性(Bena注入和装配)

  • Bean初始化:实现了各种Aware通知方法,如@BeanPostProcessor(注解初始化前置方法),@PostConstruct xml初始化方法(依赖注入后被执行)

  • 使用Bean对象

  • 销毁Bean对象

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

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

相关文章

论文解读:《数据增强:通过强化学习引导的条件生成进行文本数据扩充》

Title:<Data Boost: Text Data Augmentation Through Reinforcement Learning Guided Conditional Generation> 期刊&#xff1a;EMNLP &#xff08;顶级国际会议&#xff09; 作者 Ruibo Liu; Guangxuan Xu; Chenyan Jia; Weicheng Ma; Lili Wang; et al 出版日期 20…

基于Springboot的墙绘产品展示交易平台(有报告),Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的墙绘产品展示交易平台&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff0…

嵌入式设备摄像头基础知识

工作原理 摄像头的工作原理是&#xff0c;当光线通过镜头聚焦到图像传感器上时&#xff0c;传感器会将光信号转换为电信号&#xff0c;并将其传输给处理器进行处理。处理器通过算法对图像信号进行增强、去噪、压缩等操作&#xff0c;并将其转换为数字信号输出给计算机或其他设…

手势监听类GestureDetector Listener源码解析

手势监听类GestureDetector 前言一、GestureDetector是什么&#xff1f;二、Listener源码解析1.OnGestureListener2.OnDoubleTapListener3.OnContextClickListener4.SimpleOnGestureListener 总结 前言 在写自定义view的时候&#xff0c;涉及到了手势监听这块的知识&#xff0…

Leetcode 2948. Make Lexicographically Smallest Array by Swapping Elements

Leetcode 2948. Make Lexicographically Smallest Array by Swapping Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;2948. Make Lexicographically Smallest Array by Swapping Elements 1. 解题思路 这一题其实思路上就是分组排序&#xff0c;显然&#xff0c;对于…

C语言中#ifndef的头文件保护用法和宏定义用法

文章目录 头文件保护宏定义 #ifndef MY_HEADER_H #define MY_HEADER_H// 这里放置头文件的内容#endif // MY_HEADER_H#ifndef _error#define _error (-1) #endif这两个代码块分别用于不同的目的。 头文件保护 #ifndef MY_HEADER_H #define MY_HEADER_H// 这里放置头文件的内…

FLV 文件格式分析

前言 flv 是 flash video 的缩写&#xff0c;是 Adobe Flash payler 支持的一种流媒体播放格式。flv 是一种层级格式&#xff0c;除了一个 flv header 外&#xff0c;剩下全是由 一个个 tag 组成。tag 是由 tag 头和 tag 数据组成。tag 类型分为音频、视频、脚本&#xff0c;一…

WEB渗透—反序列化(七)

Web渗透—反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩哔_…

交换机的VRRP主备配置例子

拓朴如下&#xff1a; 主要配置如下&#xff1a; [S1] vlan batch 10 20 # interface Vlanif10ip address 10.1.1.1 255.255.255.0vrrp vrid 1 virtual-ip 10.1.1.254vrrp vrid 1 priority 200vrrp vrid 1 preempt-mode timer delay 20 # interface Vlanif20ip address 13.1.1…

2-Python与设计模式--工厂类相关模式

2-Python与设计模式–工厂类相关模式 一、快餐点餐系统 想必大家一定见过类似于麦当劳自助点餐台一类的点餐系统吧。在一个大的触摸显示屏上&#xff0c; 有三类可以选择的上餐品&#xff1a;汉堡等主餐、小食、饮料。当我们选择好自己需要的食物&#xff0c;支付完成后&…

@RequestMapping,@GetMapping,@PostMapping 的区别(详解)

HTTP请求方法 HTTP请求方法一共有9种&#xff0c;为 GET、POST、HEAD、OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT。 GET 【获取资源】本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据&#xff08;如HTML文本&#xff0c;或者图片或者视频等…

我们为什么要进行敏捷开发培训

敏捷开发是一种以人为核心、迭代、循序渐进的软件开发方法。它强调团队合作、客户需求和适应变化。进行敏捷开发培训其实有多种原因&#xff0c;我整理了一些&#xff0c;可以作为参考&#xff1a; 理解敏捷原则和实践&#xff1a; 敏捷开发不仅是一种方法论&#xff0c;更是一…

IDEA的安装与删除插件

不小心安装了一个英文转中文的插件&#xff0c;看不习惯&#xff0c;决定重新变回英文 先点击这个settings的安装 然后就看到这个下面这张图了 如果是安装就点install&#xff0c;不用了就和我一样把这个勾给去掉

MUI框架从新手入门【webapp开发教程】

文章目录 MUI -最接近原生APP体验的高性能前端框架APP开发3.25 开发记录miu框架介绍头部/搜索框&#xff1a;身体>轮播图轮播图设置数据自动跳转&#xff1a;九宫格图片九宫格图文列表底部选项卡按钮选择器手机模拟器 心得与总结&#xff1a;MUI框架在移动应用开发中的应用M…

openGauss学习笔记-133 openGauss 数据库运维-例行维护-日维护检查项

文章目录 openGauss学习笔记-133 openGauss 数据库运维-例行维护-日维护检查项133.1 检查openGauss状态133.2 检查锁信息133.3 统计事件数据133.4 对象检查133.5 SQL报告检查133.6 备份133.7 基本信息检查 openGauss学习笔记-133 openGauss 数据库运维-例行维护-日维护检查项 …

数据结构——利用堆进行对数组的排序

今天文章的内容是关于我们如何利用堆的特性对我们的数组进行排序&#xff0c;还有就是我们的TopK的问题&#xff0c;这次我们放在的是文件种&#xff0c;我们放入一亿个数字&#xff0c;然后我们取出一亿个数字中最大的十个数&#xff0c;利用上章堆的问题进行解决。 首先就是我…

计算机基础知识详细讲解

目录 一、计算机硬件 CPU&#xff08;中央处理器&#xff09;&#xff1a;负责执行计算机指令和处理数据。 内存&#xff08;RAM&#xff09;&#xff1a;用于临时存储程序和数据。 硬盘&#xff1a;用于永久性存储数据和文件。 显示器&#xff1a;用于显示图形界面和输出信…

【SQL Server2019SSMS】安装 | 卸载手册

目录 &#x1f4cb;前言 ⛳️【SQL Serverssms】安装 1. SQL Server自定义安装 2. SSMS安装 ⛳️【SQL Server】卸载 &#x1f4cb;前言 &#x1f308;个人主页&#xff1a;Sarapines Programmer &#x1f525; 系列专栏&#xff1a;本期文章收录在《宝藏工具使用手册》&am…

git日历坐标系? 手动实现github活跃/贡献图

git日历坐标系? 手动实现github活跃/贡献图 前言 在使用github或gitlab时&#xff0c;我们总能发现&#xff0c;我们一年内的活跃度能够通过一张图直观地展现出来&#xff0c;那么你是否好奇它是如何实现的&#xff0c;最近工作中也遇到这样类似的需求&#xff0c;刚开始打算…

区块链介绍

区块链提供了比特币的公共账本&#xff0c;这是一个有序的、带有时间戳的交易记录。这个系统用于防止重复消费和修改之前的交易记录。 Introduction 比特币网络中的每个完全节点都独立存储只包含该节点验证的块的区块链。当多个节点在他们的区块链中都有相同的块时&#xff0…