在Spring中,默认bean对象都是单例的,也就是通过getBean方法或者@Autowired注解获取到的bean对象都是同一个。我们可以通过@Scope注解来修改bean的模式为原型模式,这样每一次从Spring容器中获取到的bean对象就都是新的了。
通过@Scope注解及prototype参数即可修改bean为原型模式
@Component
@Scope("prototype")
为了避免prototype写错(毕竟没有提示,不过写错的时候启动会报错也无碍),建议使用ConfigurableBeanFactory接口中的常量
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
在Spring中,prototype原型模式使用的场景不多,只有当你的bean的属性中会有数据存在的时候,才需要使用原型模式,否则数据就串了不是。我自己使用过的一个场景是用EasyExcel实现导入功能的时候会使用到。
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read
在使用EasyExcel读取表格文件时,官方文档推荐的是自己进行new一个Listener对象,但是想在这个对象中使用其他service对象的话,就不能使用@Autowired了,不方便,所以我们可以考虑将这个Listener对象变成原型模式:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DemoDataListener extends AnalysisEventListener<DemoData> {
/**
* 表格中的数据
*/
private List<DemoData> dataList = new ArrayList<>();
@Autowired
private DemoService demoService;
@Override
public void invoke(DemoData data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
demoService.save(dataList);
}
}
然后在Controller里面通过Spring容器获取这个对象(注意:一定要通过容器手动获取,prototype原型模式的bean如果还通过@Autowired的形式注入的话,这个对象还是同一个,因为@Autowired只会注入一次)
DemoDataListener listener = SpringUtil.getApplicationContext().getBean(DemoDataListener.class);
获取Spring容器的部分可以参考:Spring获取上下文对象ApplicationContext的2种办法