SpringBoot多例模式,在同一个类中注入两次是否是同一个对象 – 一不小心就会写出一个重大BUG!! - 521篇

科技   2024-07-23 08:30   福建  

Spring Boot
Spring Boot
Spring Boot
Spring Boot
Spring Boot

Spring Boot

Spring Boot

Noisee AI中文站网页版 AI 音乐生成视频全新登场,快来抢先体验——国内第一个登场的中文站来袭  - 516篇

Spring的SmartLifecycle可以没用过,但没听过就不好了!- 第517篇

SpringBoot异常处理机制之自定义404、500错误提示页面 - 518篇

SpringBoot 中多例模式的神秘世界:用法区别以及应用场景,最后的灵魂拷问会吗?- 第519篇

SpringBoot开发的AI导航站技术架构剖析 —— 技术如何选型 -  第520篇



用AI做个视频:

用AI写首歌:



导读

原本是没有计划编写这么一篇文章的,这还得从说起….

话说在五百年前的一篇文章中发起了一个投票,答案竟然这么出乎意料:

这么一种投票结果,让我有点担忧,真的害怕在程序中,写了一个大大的bug出来。


准备工作

为了更清晰的进行讲解,我重新简单搭建了一个框架,Spring Boot版本选择的是 3.3.2,定义了一个多例的MyService和一个请求控制类MyController

MyController如下:

@RestController@RequestMapping("/my")public class MyController {    @Autowired    private MyService myService;    @Autowired    private MyService myService1;
@RequestMapping("/test") public Boolean test(){ System.out.println("myService:"+myService+",myService1:"+myService1); return myService == myService1; }
}

至于MyService多例还不知道怎么编写的小伙伴,或者还不清楚什么是多例的,可以关注公众号「SpringBoot」,回复关键词「476」进行查看。

问题分析

大家看看上面的输出地址是否是同一个呢?

以及==是的结果是true还是false呢?

如果你很坚定这里的答案,那么投票就会毫不犹豫的进行选择了。

输出结果如下:

myService:com.example.demo.MyService@6cdb6397,myService1:com.example.demo.MyService@621c907c

==的结果是:false

这里地址是不一样的,确实是两个地址。

那有小伙伴会有疑问了,在之前的文章不是说过:

为什么明明设置了@Scope(value=”prototype”)的属性,仍然不好使呢?这个就和一些用法上有关系了。

多例模式在进行注入时,不能使用 @Autowired,否则注入的还是单例模式,实现多例模式需要使用工厂模式;

@Autowired 在项目启动时已经将bean实例注入到引用类的成员变量中,因此在调用时是直接引用了已被初始化的成员变量,不会再从bean工厂中获取,因此没办法实现多例。也就是说多例模式,必须从bean工厂获取bean才能够实现。

这段话有几个注意点:

1@Autowired在项目启动的时候就会进行注入。

2)每次会从bean工厂进行获取,从而实现bean的属性的注入。

对于整体的注入逻辑,大家可以去看看源码。这里我简单的做个分析:

如果你能够看到我标出来的那两个注意点,那么我不解读的话,估计你也能明白什么原因了。

首先使用@Autowired注解的,Spring在项目启动的时候都会进行注入,注入的方式是从bean工厂进行获取到bean进行注入。

如果该bean是单例模式,那么就直接获取到单例的bean就可以完成注入;

如果该bean是多例模式,那么会调用beanFactory进行获取到多例的bean

所以你如果对于一个多例的bean多次引入或者在多个类中进行引入使用,那么获取到的是多个实例,而不是但实例。

那么这句话要如何解读呐?

多例模式在进行注入时,不能使用 @Autowired,否则注入的还是单例模式,实现多例模式需要使用工厂模式;

这里面的一个意思就是在一个类注入一个属性时是单例的,这么理解就通了,对于上面的测试方法,你在访问一次:

第一次:

myService:com.example.demo.MyService@6cdb6397,myService1:com.example.demo.MyService@621c907c

第二次:

myService:com.example.demo.MyService@6cdb6397,myService1:com.example.demo.MyService@621c907c

这里可以看到第二次访问的时候,确实是同一个实例了。

那到底怎么使用?

博主,你讲这个到底要做什么?我已经让你绕晕了。都不知道这个多例要怎么使用了?


情况1:每次都是不同的实例

如果你期望每次访问到的都是不同的实例,这种情况下,请使用BeanFactory的方式:

@Autowiredprivate BeanFactory factory;
@RequestMapping("/test1")public Boolean test1(){ // 此时得到的对象即为多例 MyService myService2 = factory.getBean(MyService.class); System.out.println(myService2); return myService == myService1;}

两次访问控制台打印(不同的实例):

com.example.demo.MyService@248c86d9

com.example.demo.MyService@3e4e36a5

或者ObjectFactory的方式(更推荐使用):

@Autowiredprivate ObjectFactory<MyService> myServiceObjectFactory;
@RequestMapping("/test2")public Boolean test2(){ // 此时得到的对象即为多例 MyService myService3 = myServiceObjectFactory.getObject(); System.out.println(myService3); return myService == myService1;}

两次访问控制台打印(不同的实例):

com.example.demo.MyService@23a14ec9

com.example.demo.MyService@2a4b7c38


情况2:多种业务场景

如果你只是多种的业务场景下,期望多例的话,那么就可以使用@Autowire的方式进行使用。这里我使用最近开发的项目的案例说明一下可能会更好的理解。

一个项目中有两个如下场景:

1)场景一:AI写歌中要使用Redis的队列服务MyRedisQuqueService

1)场景二:AI生成视频中要使用Redis的队列服务MyRedisQuqueService

如果每个场景使用同一个队列,那么使用单例就可以搞定了,不需要搞这么复杂,我这里是不同场景,使用不同的队列,那么这个队列信息的配置,就会变成这个场景的属性,如果是单例的话,那么两个场景会互相影响,如果是多例下的@Autowired,那么是两个实例,属性的修改不会互相影响。

如果大家对于这两个AI项目感兴趣,想体验的话,可以关注公众号「未来AI视界」 或者直接点击下面公众号一键进入。


计520+
Spring Boot
Spring Boot
Spring Boot
Spring Boot
Spring Boot

Spring Boot

Spring Boot

抖音主播/电商人员有福了,利用Suno创作产品宣传,让产品动起来-小米Su7 - 第510篇

Spring Boot整合ElasticSearch实战 - 第511篇

Transaction rolled back because it has been marked as - 第512篇

五音不全也浪漫,521清华学霸为爱人写歌 - 第513篇

一文讲清楚SpringBoot项目打包jar后运行报错template might not exist - 第514篇

idea springboot woff/woff2/eot/ttf/svg等小图标不显示的问题 - 第515篇

Noisee AI中文站网页版 AI 音乐生成视频全新登场,快来抢先体验——国内第一个登场的中文站来袭  - 516篇

Spring的SmartLifecycle可以没用过,但没听过就不好了!- 第517篇

SpringBoot异常处理机制之自定义404、500错误提示页面 - 518篇

SpringBoot 中多例模式的神秘世界:用法区别以及应用场景,最后的灵魂拷问会吗?- 第519篇

SpringBoot开发的AI导航站技术架构剖析 —— 技术如何选型 -  第520篇

SpringBoot
Suno AI制作音乐,Viggle AI - 照片跳舞,AI音乐,Noisee AI制作MV。Spring Boot技术。博客已有400+,文章特色:一个知识点一个系列、让技术变得简单、文章轻松幽默,悟纤和师傅趣谈更是轻松有趣。
 最新文章