spring的scope为prototype的bean的正确使用方法

2024-05-26 19:48

本文主要是介绍spring的scope为prototype的bean的正确使用方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

此博文可配合 BGDI 组件实现简单Spring IOC容器及其依赖注入特性。搭配 解决 Java 反射时对象之间的循环依赖问题 解决 bean 对象实例之间的循环依赖问题。

 

引用博客

spring的bean的作用域有 singleton(无状态),prototype(有状态),session,request 等,本来以为很简单,但实际面试中,90%的人根本就不知道如何使用,其中不乏工作5,6年以上的,只知道有这几个作用域,由此可以看出大部分java开发人员基础真是差啊。

很多人看教程里面,使用prototype作用域的bean代码里面,获取bean的方法都是用appContext.getBean方法获取,但实际工作编码中,我们一般是通过方法的参数注入。

@Service
@Scope(value="prototype")
public class MainServices {// ...
}

如下,每次注入新的MainServices实例:

@GetMapping("/test3")
public HashMap<String, Object> test2(@Autowired MainServices s) {// ...
}

但要在一个controller里面注入一个多例的service需要怎么实现?(工作中不应该这样用,而是应该通过参数注入)

如下:

@RestController
public class MainController {@AutowiredMainServices services;
}

很明显controller只有一个,service也有只一个,这样定义是不能达到效果的!自己测试一下就知道。

正确的方法是如下,需要指定使用代理如果注入的是接口可以用INTERFACES,否则用TARGET_CLASS

@Service
@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class MainServices {// ...
}

这样spring就会注入一个代理类,然后每次调用的时候会根据你的作用域去获取bean。只有不是singleton的bean,注入的都是代理类。

很简单的一个知识点,我想说明的是,看教程一定要自己尝试一下,并了解他的工作原理,思考ioc,aop,作用域的关系。

所以你知道为什么在controller里面注入request没有线程安全问题了吧?!

@Autowired
HttpServletRequest request;

这里request返回的是类名是com.sun.proxy.$Proxy62,很明显使用的jdk的动态代理。

 


@Scope 注解使用

全局配置

@ComponentScan(basePackages = {"com.jaemon.sdk"}, scopedProxy = ScopedProxyMode.TARGET_CLASS)
public class SpingBootApplication {// ...
}

默认值: ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

类级别配置

// 如果注入的是接口, 可以使用 ScopedProxyMode.INTERFACES, 否则使用 ScopedProxyMode.TARGET_CLASS
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.INTERFACES)
public class BizService {// ...
}@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserServiceImpl implements IUserService {// ...
}

如果在 @ComponentScan 中设置了全局配置, 则 @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)可以无需设置 proxyMode 属性的值, 默认 scopedProxy 使用的是全局配置的值。

 

代码验证

注入类

@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class BizService {private String uniqueKey;public BizService() {this.uniqueKey = UUID.randomUUID().toString().replace("-", "").toUpperCase();}public String uniqueKey() {return this.uniqueKey;}
}

注入接口

public interface IUserService {String userId();
}@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.INTERFACES)
public class UserServiceImpl implements IUserService {private String userId;public UserServiceImpl() {this.userId = UUID.randomUUID().toString().replace("-", "").toUpperCase();}@Overridepublic String userId() {return userId;}
}
@RestController
@RequestMapping("/api")
@Slf4j
public class MyController {// 注入类@Autowiredprivate BizService bizService;// 注入接口@Autowiredprivate IUserService userService;@GetMapping(value = "/query")public Response query() {String uniqueKey = bizService.uniqueKey();String userId = userService.userId();return Response.success(userId, uniqueKey);}
}

重复请求 query 接口, 如果返回结果中 userId 和 uniqueKey 每次都不一样, 说明 scope=prototype 配置生效

 

参考地址

  • spring的scope为prototype的bean的正确使用方法

这篇关于spring的scope为prototype的bean的正确使用方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1005427

相关文章

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

Jsoncpp的安装与使用方式

《Jsoncpp的安装与使用方式》JsonCpp是一个用于解析和生成JSON数据的C++库,它支持解析JSON文件或字符串到C++对象,以及将C++对象序列化回JSON格式,安装JsonCpp可以通过... 目录安装jsoncppJsoncpp的使用Value类构造函数检测保存的数据类型提取数据对json数

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python