【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 {
    @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.mfbz.cn/a/193354.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openGauss学习笔记-132 openGauss 数据库运维-查看openGauss状态

文章目录 openGauss学习笔记-132 openGauss 数据库运维-查看openGauss状态132.1 背景信息132.2 前提条件132.3 操作步骤132.4 参数说明132.5 示例 openGauss学习笔记-132 openGauss 数据库运维-查看openGauss状态 132.1 背景信息 openGauss支持查看整个openGauss的状态&#…

自动驾驶学习笔记(十一)——高精地图

#Apollo开发者# 学习课程的传送门如下,当您也准备学习自动驾驶时,可以和我一同前往: 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo Beta宣讲和线下沙龙》免费报名—>传送门 文章目录 前言 高精地图 地图采集 底图制作 地图…

FLASK博客系列4——再谈路由

最近好像拖更有点久了。抱歉抱歉~ 今天我们继续来聊聊路由(其实就是我上次偷懒剩下一点没讲完)。 通过上次的文章,我们基本了解了Flask中的路由,是不是比较简单呢?别急,今天来点猛料。 一、路由之HTTP方法绑…

1233:单词倒置(C语言)

题目描述 最近birdfly收到了女友的几份信件,为了只要他俩知道信件的秘密,女友把信件里的每个单词都倒置了。这样只有birdfly将它们倒置过来才能明白女友的心思了。为此birdfly还特意请你编写程序帮他解决一下这个问题。 简单起见假定每封信只包含英文单词…

B 树和 B+树 的区别

文章目录 B 树和 B树 的区别 B 树和 B树 的区别 了解二叉树、AVL 树、B 树的概念 B 树和 B树的应用场景 B 树是一种多路平衡查找树,为了更形象的理解。 二叉树,每个节点支持两个分支的树结构,相比于单向链表,多了一个分支。 …

Android aidl的简单使用

一.服务端 1.创建aidl文件,然后记得build下生成java文件 package com.example.aidlservice31;// Declare any non-default types here with import statementsinterface IMyAidlServer {// 接收一个字符串参数void setData(String value);// 返回一个字符串String …

地理坐标系转换

1.EPSG代码 搜索地理坐标系对应的EPSG代码 https://epsg.io/ 常用的地理坐标系EPSG代码: 2. 坐标系转换 转换网址: https://epsg.io/transform (1)修改 input coordinate system 和 output coordinate system, 可以…

P19 C++ 构造函数的成员初始化列表

目录 前言 01 如果不用成员列表如何初始化变量 02 成员列表初始化 03 为什么要使用成员列表初始化呢? 04 案例代码 前言 本期我们聊聊构造函数初始化列表。 你应该经常使用成员初始化列表,如果你不喜欢这种代码风格,建议你还是慢慢习惯吧…

大导演王晶进军短剧,小程序短剧质量再上一层,短剧小程序的

在2023年11月26号,大导演王晶在横店进行开机仪式,短剧《亿万傻儿子》开拍,该短剧题材为都市、男频。 目前短剧是比较热门,大导演王晶拍摄短剧可谓是将短剧的质量提高一个层次。 侧面反映了短剧已经是非常广泛了。后续发展就是哪家…

Aapche Dubbo 不安全的 Java 反序列化 (CVE-2019-17564)

漏洞描述 Apache Dubbo 是一个高性能的、基于 Java 的开源 RPC 框架。 Apache Dubbo 支持不同的协议,它的 HTTP 协议处理程序是 Spring Framework 的 .org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter Spring Framework 的安全警告显示&am…

ProFTPD-1.3.3c Backdoor Command Execution漏洞复现+poc

https://www.whereisk0shl.top/post/proftpd-1.3.3chou-men-fen-xi https://github.com/proftpd/proftpd 在官网和官方github上找了一圈1.3.3c版本的proftpd,应该是漏洞太多,官方把下了 https://blog.csdn.net/morrino/article/details/115836400 这个文…

ssm+vue的公司安全生产考试系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频: ssmvue的公司安全生产考试系统(有报告)。Javaee项目,ssm vue前后端分离项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结…

Huggingface 超详细介绍

Hugging face 起初是一家总部位于纽约的聊天机器人初创服务商,他们本来打算创业做聊天机器人,然后在github上开源了一个Transformers库,虽然聊天机器人业务没搞起来,但是他们的这个库在机器学习社区迅速大火起来。目前已经共享了超…

AI 绘画 | Stable Diffusion 提示词扩展插件

前言 提示词对于Stable Diffusion AI绘画来说非常重要, 由于Stable Diffusion 支持英文提示词,对于英文不好的朋友,每次都要切换翻译网站去翻译,很不方便,下面介绍两款Stable Diffusion 提示词扩展插件,让你写提示词更轻松。 sd-webui-prompt-all-in-one 提示词多合一插…

d3dx9_39.dll丢失问题及其解决方法,3分钟快速搞定d3dx9_39.dll文件

d3dx9_39.dll丢失你们都遇到过么?其实这个dll文件的丢失,一般是喜欢玩游戏的朋友会经常遇到的,小编觉得很有必要来给大家详细的说一下这方面的事情,教大家关于d3dx9_39.dll丢失问题及其解决方法,好了,我们废…

区块链存证:杭州互联网法院备选方案之一

文章目录 背景上报的存证系统设计备选方案***总体原则******分层架构******基础节点******存证链******存证业务******存证接入******通用功能******跨链对接架构***业务流程描述用户发起原创内容存证(对应上图中左边1,2,3活动)发现侵权行为,…

Echart力引导依赖关系布局图

Echarts ECharts(Enterprise Charts)Apache ECharts是百度开发的一款开源的 JavaScript 数据可视化库。它提供了丰富的图表和图形,适用于在 Web 应用程序中创建各种交互式和动态的数据可视化图表。ECharts支持各种图表类型,包括折…

云平台系列:What is Serverless (FaaS、BaaS)

文章目录 前言IaaS 与 PaaS 和SaaSIaaS(基础设施即服务)PaaS(平台即服务)SaaS(软件即服务)聊聊 IaaS What is Serverless?FaaS(函数即服务)执行适应场景 BaaS(后端即服务…

OCR常用数据集_看数据集区分可识别语言

这里写目录标题 COCO-TEXT 英文Total-Text 英文少量中文IIIT5K[50]、IC03[44]、IC13[34]、IC15[33]、CT80[56]MJSynth 英文SynthText分层文本数据集 (HierText) 英文TextOCR和IntelOCR ???Multi-language dataset (IC19)RCTW17 主要中文MSRA-…

Webpack——Webpack简介

1、什么是Webpack? Webpack是一个开源的JavaScript模块打包工具,其最核心的功能是解决模块之间的依赖,把各个模块按照特定的规则和顺序组织在一起,最终合并为一个JS文件(有时会有多个,这里讨论的只是最基本…
最新文章