Spring singleton bean 与 prototype bean 的依赖

本文同步至:http://www.waylau.com/spring-singleton-beans-with-prototype-bean-dependencies/

##问题

我们知道,Spring bean 默认的 scope 是 singleton(单例),但有些场景(比如多线程)需要每次调用都生成一个实例, 此时 scope 就应该设为 prototype。如:

<!-- more -->
1@Component 2@Scope("prototype") 3public class DadTask implements Runnable { 4 static Logger logger = Logger.getLogger(DadTask.class); 5 6 @Autowired 7 DadDao dadDao; 8 9 private String name; 10 /** 11 * 12 */ 13 public DadTask setDadTask(String name) { 14 this.name = name; 15 return this; 16 } 17 18 /* (non-Javadoc) 19 * @see java.lang.Runnable#run() 20 */ 21 @Override 22 public void run() { 23 logger.info("DadTask:"+this + ";DadDao:"+dadDao + ";"+dadDao.sayHello(name) ); 24 //logger.info("Dad:"+name); 25 } 26 27}

但是,如果 singlton bean 依赖 prototype bean ,通过依赖注入方式, prototype bean 在 singlton bean 实例化时会创建一次(只一次), 比如:

1@Service 2public class UserService { 3 4 @Autowired 5 private DadTask dadTask; 6 7 public void startTask() { 8 ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2); 9 10 scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lily"), 1000, 2000, TimeUnit.MILLISECONDS); 11 scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lucy"), 1000, 2000, TimeUnit.MILLISECONDS); 12 } 13}

我希望调度“Lily” 和 “Lucy” 两个线程,实际上,它只给我初始化一个实例(这样就线程非安全了)。

解决

如果 singlton bean 想每次都去创建一个新的 prototype bean 的实例, 需要通过方法注入的方式。 可以通过实现 ApplicationContextAware 接口,来获取到 ApplicationContext 实例, 继而通过 getBean 方法来获取到 prototype bean 的实例。我们的程序需要修改如下:

1@Service 2public class UserService implements ApplicationContextAware { 3 4 @Autowired 5 private DadTask dadTask; 6 7 private ApplicationContext applicationContext; 8 9 public void startTask() { 10 ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2); 11 12 // 每次都拿到 DadTask 的实例 13 dadTask = applicationContext.getBean("dadTask", DadTask.class); 14 scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lily"), 1000, 2000, TimeUnit.MILLISECONDS); 15 dadTask = applicationContext.getBean("dadTask", DadTask.class); 16 scheduledThreadPoolExecutor.scheduleAtFixedRate(dadTask.setDadTask("Lucy"), 1000, 2000, TimeUnit.MILLISECONDS); 17 } 18 19 @Override 20 public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { 21 this.applicationContext = applicationContext; 22 23 } 24}

OK ,问题解决

源码

https://github.com/waylau/spring-framework-4-demosbeanScope 目录

参考

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )