系列十七、各种各样的bean

news2024/11/26 17:47:11

一、Spring bean

1.1、概述

一句话,被Spring容器管理的bean就是Spring bean。

二、Java bean VS Spring bean

2.1、概述

Java bean是程序员自己new 出来的,Spring bean是Spring工厂创建出来的。

三、配置bean的方式

3.1、概述

  所谓配置bean,是指如何将一个普通的Java类交由Spring容器进行管理。

3.2、配置方式

# 第一种
xml
 
# 第二种
xml + 注解
 
# 第三种
JavaConfig
 
# 第四种
@Import

四、@Component vs @Bean

4.1、概述

        @Component是Spring中的一个注解,通常标识在一个类上面,用于说明该类是被Spring容器管理的,其内部是通过反射机制调用构造方法完成实例化,@Bean也是一个注解,标识在方法上,通常和@Configuration注解搭配使用,其方法名就是bean的name,通过这种方式程序员可以自己控制bean的实例化过程。

4.2、案例

4.2.1、Car

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:28
 * @Description:
 */
@Component
@Getter
@Setter
public class Car implements Serializable {

    private String name;
    private String description;

    public Car() {
        System.out.println("Car的无参构造执行了...");
    }
    public Car(String name, String description) {
        this.name = name;
        this.description = description;
        System.out.println("Car的有参构造执行了...");
    }
}

4.2.2、Tank

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:31
 * @Description:
 */
@ToString
@Getter
@Setter
public class Tank implements Serializable {

    private String name;
    private String description;
    private String producer;

    public Tank() {
        System.out.println("Tank的无参构造执行了...");
    }

    public Tank(String name, String description, String producer) {
        System.out.println("Tank的有参构造执行了...");
        this.name = name;
        this.description = description;
        this.producer = producer;
    }
}

4.2.3、MySpringConfig

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:29
 * @Description:
 */
@Configuration
@ComponentScan(basePackages = {"org.star"})
public class MySpringConfig {

    @Bean
    public Tank tank() {
        Tank tank = new Tank("东风0001","加满油能跑10000公里","中国");
        return tank;
    }

}

4.2.4、AopFullAnnotationMainApp

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);

        Car car = context.getBean("car", Car.class);
        Tank tank = context.getBean("tank", Tank.class);
        log.info("car:{},tank:{}", car, tank);

    }

}

五、 Spring bean线程安全问题

5.1、概述

        我们知道Spring中的bean,默认情况下是单例的,那么Spring中的bean是线程安全的吗?这个需要分情况考虑,bean中是否存在成员变量?bean中的成员变量是怎么处理的?...,针对bean的状态会有不同的处理方案:

        情况一:bean是单例的;

        情况二:bean是多例的(不会存在线程安全问题);

出现线程安全问题的原因:单实例bean中存在成员变量,并且有对这个bean进行读写的操作,因此出现了线程安全的问题。

5.2、演示Spring bean存在线程安全

5.2.1、UserService

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:55
 * @Description: 
 */
@Service
public class UserService {

    private String username;

    public String welcome(String name) {
        username = "welcome " + name;
        try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}
        return username;
    }

}

5.2.2、MySpringConfig

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:29
 * @Description:
 */
@Configuration
@ComponentScan(basePackages = {"org.star"})
public class MySpringConfig {

}

5.2.3、AopFullAnnotationMainApp

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);
        UserService userService = context.getBean(UserService.class);
        Random r = new Random();
        String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                int index = r.nextInt(5);
                String name = nameArray[index];
                log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService.welcome(name));
            }, "线程" + i).start();
        }
    }

}

5.3、解决方法

        上面代码演示了Spring中的bean的确存在着线程安全问题,出现问题我们要解决问题,针对Spring中bean中存在的线程安全,我们可以通过以下方式进行解决:

        方案一:将成员变量修改为局部变量(单例bean);

        方案二:使用ThreadLocal(单例bean);

        方案三:使用同步锁synchronized(单例bean);

        方案四:将单例bean设置为多例的;

        案例代码如下

5.4、将成员变量修改为局部变量(单例bean)

5.4.1、UserService2

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:55
 * @Description: 单例bean线程不安全(解决方式一:将成员变量修改为局部变量)
 */
@Service
public class UserService2 {

    public String welcome(String name) {
        String username = "welcome " + name;
        try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}
        return username;
    }

}

5.4.2、MySpringConfig(同上) 

5.4.3、AopFullAnnotationMainApp 

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);

        UserService2 userService2 = context.getBean(UserService2.class);
        Random r = new Random();
        String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                int index = r.nextInt(5);
                String name = nameArray[index];
                log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService2.welcome(name));
            }, "线程" + i).start();
        }
    }
}

5.5、使用ThreadLocal(单例bean)

5.5.1、UserService3

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:55
 * @Description: 单例bean线程不安全(解决方式二:使用ThreadLocal)
 */
@Service
public class UserService3 {

    private ThreadLocal<String> threadLocal = new ThreadLocal<>();

    public String welcome(String name) {
        threadLocal.set("welcome" + name);
        try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}
        return threadLocal.get();
    }

}

5.5.2、MySpringConfig(同上)

5.5.3、AopFullAnnotationMainApp

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);

        UserService3 userService3 = context.getBean(UserService3.class);
        Random r = new Random();
        String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                int index = r.nextInt(5);
                String name = nameArray[index];
                log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService3.welcome(name));
            }, "线程" + i).start();
        }

    }
}

5.6、 使用同步锁synchronized(单例bean)

5.6.1、UserService4

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:55
 * @Description: 单例bean线程不安全(解决方式三:使用同步锁synchronized)
 */
@Service
public class UserService4 {

    private String username;

    public synchronized String welcome(String name) {
        username = "welcome " + name;
        try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}
        return username;
    }

}

5.6.2、MySpringConfig(同上)

5.6.3、AopFullAnnotationMainApp 

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);

        UserService4 userService4 = context.getBean(UserService4.class);
        Random r = new Random();
        String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                int index = r.nextInt(5);
                String name = nameArray[index];
                log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService4.welcome(name));
            }, "线程" + i).start();
        }
    }
}

5.7、 将单例bean设置为多例的

5.7.1、UserService5

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/26 14:55
 * @Description: 单例bean线程不安全(解决方式四:将单例bean设置为多例的)
 */
@Scope("prototype")
@Service
public class UserService5 {

    private String username;

    public String welcome(String name) {
        username = "welcome " + name;
        try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}
        return username;
    }

}

5.7.2、MySpringConfig(同上)

5.7.3、AopFullAnnotationMainApp 

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/23 15:14
 * @Description:
 */
@Slf4j
public class AopFullAnnotationMainApp {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringConfig.class);

        Random r = new Random();
        String[] nameArray = new String[]{"张三", "李四", "王五", "赵六", "钱七"};
        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                UserService5 userService5 = context.getBean(UserService5.class);
                int index = r.nextInt(5);
                String name = nameArray[index];
                log.info("当前线程:{},当前索引:{},当前name的值:{},当前取出的值:{}", Thread.currentThread().getName(), index, name, userService5.welcome(name));
            }, "线程" + i).start();
        }
    }
}

 

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

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

相关文章

【精选必读】MyBatis关联查询及注解开发

文章目录 MyBatis关联查询MyBatis一对一关联查询创建持久层接口创建映射文件配置文件注册映射文件测试一对一关联查询 MyBatis一对多关联查询创建持久层接口创建映射文件测试一对多关联查询 MyBatis多对多关联查询创建持久层接口创建映射文件测试多对多关联查询 MyBatis分解式查…

性能测试必看系列之Jmeter:硬件性能监控指标

硬件性能监控指标 一、性能监控初步介绍 性能测试的主要目标 1.在当前的服务器配置情况&#xff0c;最大的用户数 2.平均响应时间ART&#xff0c;找出时间较长的业务 3.每秒事务数TPS&#xff0c;服务器的处理能力 性能测试涉及的内容 1.客户端性能测试&#xff1a;web前…

一. BEV感知算法介绍

目录 前言1. BEV感知算法的概念2. BEV感知算法数据形式3. BEV开源数据集介绍3.1 KITTI数据集3.2 nuScenes数据集 4. BEV感知方法分类4.1 纯点云方案4.2 纯视觉方案4.3 多模态方案 5. BEV感知算法的优劣6. BEV感知算法的应用介绍7. 课程框架介绍与配置总结下载链接参考 前言 自动…

Nginx常见的中间件漏洞

目录 1、Nginx文件名逻辑漏洞 2、Nginx解析漏洞 3、Nginx越权读取缓存漏洞 这里需要的漏洞环境可以看&#xff1a;Nginx 配置错误导致的漏洞-CSDN博客 1、Nginx文件名逻辑漏洞 该漏洞利用条件有两个&#xff1a; Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7 php-fpm.conf中的s…

由于找不到vcruntime140.dll无法继续执行代码-提供5个修复方法分你对比

摘要&#xff1a;本文将介绍vcruntime140.dll文件的作用及其在程序运行中的重要性&#xff0c;并提供五个解决vcruntime140.dll无法继续执行的方法。 一、vcruntime140.dll文件介绍 vcruntime140.dll是Windows操作系统中的一项重要文件&#xff0c;它是由Microsoft Visual C提…

交换技术-电路交换-报文交换-分组交换

交换技术是指主机之间、通信设备之间或主机与通信设备之间为交换信息所采用的数据格式和交换装置的方式。按交换技术可分为&#xff1a;电路交换、报文交换和分组交换。 电路交换 交换(switching)&#xff0c;就是按照某种方式动态地分配传输线路的资源。 电路交换是在源结点…

Scrapy爬虫异步框架之持久化存储(一篇文章齐全)

1、Scrapy框架初识&#xff08;点击前往查阅&#xff09; 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于…

如何在Ubuntu系统上安装MongoDB

简单介绍 MongoDB是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。MongoDB旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB将数据存储为一个文档&#xff0c;数…

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的状态&#…

【从亮机卡开始的云炼丹】环境配置记录debug

要更改Anaconda环境的默认路径到D盘 可以按照以下步骤操作&#xff1a; 1. 打开Anaconda Prompt&#xff08;或者命令行窗口&#xff09;。 2. 输入以下命令更改Anaconda环境的默认路径到D盘&#xff1a; conda config --set envs_dirs D:\Anaconda\envs 这将把Anaconda环境…

【挑战业余一周拿证】二、在云中计算 - 第 2 节 - Amazon EC2 实例类型

第 2 节 - Amazon EC2 实例类型 如果我们想让企业尽可能高效地运作&#xff0c;那就一定要确保员工的技能组合适合他们的角色&#xff0c;就 像我们的咖啡店有不同类型的员工一样&#xff0c;亚马逊云科技也有不同类型的 EC2 实例。每种实例类型 都归属于一个实例系列&#x…

jQuery_08 each函数的使用

each函数的使用 可以循环数组&#xff0c;json&#xff0c;dom对象数组 1.$.each(要循环的内容,function(index,element){处理函数}) 要循环的内容可以是数组&#xff0c;json对象&#xff0c;dom数组 function&#xff1a;循环的处理函数 每个成员都会执行这个函数一次 index&…

Rust语言入门教程(七) - 所有权系统

所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源&#xff0c;也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统&#xff0c;才使得编译器能够提前暴露代码中的错误&#xff0c;并给出我们必要且精准的错误提示。 所有权系统的三个规则…

【Linux】Linux项目自动化构建工具 --- make / makefile

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和Linux还有算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 …

tidyverse数据特征学习

目录 特征缩放 1&#xff0c;标准化-scale 2&#xff0c;归一化-rescale 3&#xff0c;行规范化 4&#xff0c;数据平滑 特征变换 1. 非线性特征 2. 正态性变换 3. 连续变量离散 特征降维 特征缩放 不同数值型特征的数据量纲可能相差多个数量级&#xff0c;这对很多…

ZGC 垃圾回收过程

ZGC&#xff08;Z Garbage Collector&#xff09;是Java平台上的一种垃圾收集器&#xff0c;它是由Oracle开发的&#xff0c;旨在解决大堆的低延迟垃圾收集问题。ZGC是一种并发的分代垃圾收集器&#xff0c;它主要针对具有大内存需求和低停顿时间要求的应用程序 ZGC的核心概念及…

人力资源管理后台 === 首页+部署

目录 1.首页-echarts图表的应用 2.首页-echarts图表的按需导入 3.路由模式-将路由改成history模式 4. 打包分析-分析 5.CDN加速 6.项目打包-安装nginx 7.mac/windows环境下nginx部署启动项目 8.nginx解决history的404问题 9.nginx配置代理解决生产环境跨域问题 1.首页-…

复数的几何意义

1、复平面&#xff0c;复数的其它表示法 (1)几何表示法 直角平面坐标&#xff1a; 复平面 实轴&#xff0c;虚轴 (2)向量表示法 向量 模&#xff1a; 复数加减法可用向量的三角形法则或者平行四边形法则 (3)结论 (两边之和大于第三边) ((两边之差大于第三边)) *辐角&am…

「Verilog学习笔记」非整数倍数据位宽转换24to128

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 要实现24bit数据至128bit数据的位宽转换&#xff0c;必须要用寄存器将先到达的数据进行缓存。24bit数据至128bit数据&#xff0c;相当于5个输入数据第6个输入数据的拼接成一…

Educational Codeforces Round 158 [Rated for Div. 2]

A. Line Trip 还算比较简单的&#xff0c;不过本蒟蒻一开始以为是二分答案&#xff0c;二分写到一半突然想到油量直接取两个加油站之间的最大距离就好了。 最大距离能过&#xff0c;剩下必然都能过&#xff0c;要特判a[n]~x距离是两倍&#xff0c;因为x没有加油站&#xff0c…