【Java Spring】SpringBoot Bean详解

news2024/11/24 3:07:22

文章目录

    • 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 {
    @Autowired
    private 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;

    @Autowired
    public 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;
    }

    @Bean
    public 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 解决方式:

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

     @Autowired
     private 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 {

    @Autowired
    private User user1;

    public void getUser() {
        System.out.println("User1:" + user1);
        User u = user1;
        u.setName("李四");
        System.out.println("u:" + u);
    }
}

@Controller
public class UserAdviceController {

    @Resource
    private 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)
    @Bean
    public 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.coloradmin.cn/o/1260936.html

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

相关文章

Clion+Ubuntu(WSL)+MySQL8.0开发环境搭建

1. 下载 MySQL 源码 访问 MySQL 官方网站(MySQL :: Download MySQL Community Server)并下载 MySQL 8.0 的源码包(mysql-boost-8.0.31.tar.gz)。 2. 安装编译依赖 1)更换镜像源 参考:Linux Ubuntu 修改…

管式真空加热炉高精度真空控制系统技术升级改造解决方案

摘要:针对用户提出的高温石英管加热炉真空度控制系统的升级改造,以及10~100Torr的真空度控制范围,本文在分析现有真空控制系统造成无法准确控制所存在问题的前提下,提出了切实可行的解决方案。解决方案对原有的无PID控制功能的压强…

蓝桥杯day01——负二进制数相加

题目描述 给出基数为 -2 的两个数 arr1 和 arr2,返回两数相加的结果。 数字以 数组形式 给出:数组由若干 0 和 1 组成,按最高有效位到最低有效位的顺序排列。例如,arr [1,1,0,1] 表示数字 (-2)^3 (-2)^2 (-2)^0 -3。数组形式…

PyRFC 服务器端编程要点

PyRFC 支持服务器端编程。什么是服务器端编程?有哪些技术要求?可以参考我的另外一篇博客:SAP接口编程 之JCo3.0系列(06) 。本篇主要介绍 PyRFC 的技术实现。 要点 服务器端编程的主要作用是实现 ABAP 主动调用服务器端编程需要首先在 ABAP…

深度学习黎明时期的LeNet:揭开卷积神经网络的序幕

在深度学习的历史长河中,Yann LeCun 的 LeNet 是一个里程碑式的研究成果,它为后来的卷积神经网络(Convolutional Neural Networks,CNN)的发展奠定了基础。LeNet 的诞生标志着深度学习黎明时期的到来,为人工…

11.22数电第四次报告

《数字逻辑》实验报告 姓名 贾轲 年级 22 学号 20220669 专业、班级 计算机科学与技术计卓01 实验名称 实验十五 摩尔状态机序列检测器&实验十六 米利状态机序列检测器 实验时间 2023.11.23 实验地点 DS1410 实验成绩 实验性质 □验证性 □设计性 □…

oracle查询开始时间和结束时间之间的连续月份

SELECT TO_CHAR(ADD_MONTHS(TO_DATE(2023-01,YYYY-MM), ROWNUM - 1), YYYY-MM) AS fmonth FROM DUALCONNECT BY ROWNUM < CEIL(MONTHS_BETWEEN(TO_DATE(2023-11, YYYY-MM), TO_DATE(2023-01,YYYY-MM))1)

入侵redis之准备---Centos7上面部署redis

入侵redis之准备—Centos7上面部署redis 编写这个部署redis&#xff0c;只是为了另一个文章入侵redis做准备&#xff0c;网上还有好多类似的文章&#xff0c;这个单纯的就是部署安装&#xff0c;并简单的测试使用以下 关联其他文章 [1]VMware上面安装部署centos7镜像系统【详细…

解决:ValueError: binary mode doesn‘t take an encoding argument

解决&#xff1a;ValueError: binary mode doesn’t take an encoding argument 文章目录 解决&#xff1a;ValueError: binary mode doesnt take an encoding argument背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时&#…

淼一科技为互联网企业销毁硬盘数据 拆除机房设备

在上海这座繁华的大都市&#xff0c;淼一科技以其专业的服务和卓越的技术&#xff0c;为众多互联网企业提供硬盘数据销毁和机房设备拆除服务。作为业界领先的数据安全解决方案提供商&#xff0c;淼一科技致力于保障客户数据的安全与隐私&#xff0c;为客户创造更高的商业价值。…

公网穿透和RTC

RTC RTC 是 Real-Time Communication 的简写&#xff0c;正如其中文名称 “即时通讯” 的意思一样&#xff0c;RTC 协议被广泛用于各种即时通讯领域&#xff0c;诸如&#xff1a; 在线教育&#xff1b;直播中的主播连麦 PK&#xff1b;日常生活的音视频电话&#xff1b;.....…

KaiwuDB 多模数据库-时序性能优化

随着物联网领域的快速发展&#xff0c;时序数据的产生和处理需求不断增长。为了满足实时性、高效性和准确性的要求&#xff0c;数据库需要进行时序性能优化&#xff0c;以提供快速的数据写入、实时查询和高效的数据存储与处理能力。 本期直播介绍了时序数据和时序数据库特征以…

ESP32-Web-Server编程-CSS 基础 2

ESP32-Web-Server编程-CSS 基础 2 概述 如上节所述&#xff0c;可以使用外部 CSS 文件来修饰指定的 HTML 文件。 外部引用 - 使用外部 CSS 文件。 当样式需要被应用到很多页面的时候&#xff0c;外部样式表将是理想的选择。使用外部样式表&#xff0c;就可以通过更改一个文件…

NV040C语音芯片:让自助ATM机使用更加安全快捷

近年来&#xff0c;移动支付方式的兴起、银行加强线上化服务、数字人民币项目推进等因素的影响&#xff0c;人们使用ATM机的频率呈现小幅度的下降趋势。然而&#xff0c;自助ATM机并未从我们的视野中消失&#xff0c;它们仍然在金融领域发挥着重要的作用。未来&#xff0c;ATM机…

分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测

分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测 目录 分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测&#xff08;完…

成都爱尔樊映川院长讲解常见眼底病有哪些

一提到“眼底”这个眼科常用词汇&#xff0c;许多非医疗行业人士认为在眼球下方&#xff0c;其实不然&#xff0c;那眼底在哪呢?眼底其实是眼球内后部的组织&#xff0c;即眼球的内膜——视网膜、视乳头、黄斑和视网膜中央动静脉。 眼底病是一种病种繁多&#xff0c;病因复杂&…

Python Subprocess教程:创建和管理子进程的完整指南

更多Python学习内容&#xff1a;ipengtao.com 在Python中&#xff0c;Subprocess模块为我们提供了强大的工具&#xff0c;使得创建和管理子进程变得十分便捷。本文将深入探讨Subprocess的各种功能和用法&#xff0c;通过丰富的示例代码&#xff0c;带你领略其强大的子进程管理能…

Compensated Summation/Kahan‘s Summation的理解

阅读《Efficient Generation of Error-Inducing Floating-Point Inputs via Symbolic Execution》这篇论文时&#xff0c;文中提到的Commpensated Summation没看太懂&#xff0c;代码如下&#xff1a; 查阅资料发现Compensated Summation也叫Kahan’s Summation&#xff0c;该…

自己动手实现一个深度学习算法——七、卷积神经网络

文章目录 1.整体结构2.卷积层1&#xff09;全连接层存在的问题2&#xff09;卷积运算3&#xff09;填充4&#xff09;步幅5&#xff09;3维数据的卷积运算6&#xff09;结合方块思考7&#xff09;批处理 3.池化层1&#xff09;池化层的特征 4.卷积层和池化层的实现1&#xff09…

C Primer Plus讲解前置说明

说明 本来是准备接着写下去&#xff0c;写着就发现思路整理的有点杂乱无章。果然是“想一千次&#xff0c;不如去做一次”。所以这次准备基于《C Primer Plus》第六版给大家分享一下&#xff0c;也是自己梳理的一个过程。有关C语言的书很多&#xff0c;我选这本也恰巧是因为以前…