spring创建多例

最近遇到一个了问题,简单的描述一下。
按模块调用接口,比如a、b、c、d四个模块每个模块2~3个接口,一笔交易最多四个模块,所以在调用时每个模块开启一个线程。那么问题来了模块线程在主线程中是通过注解自动注入的(模块线程依赖其他的bean,所以不能new),即模块线程单例的。
多线程环境下,把接口调用需要使用到的参数从主线程传到模块线程时,虽然在主线程中每一次都new一个新的参数,但因为模块线程是单例的,所以会有可能产生脏读的可能性(参数被其他线程覆盖掉了)

明确了问题后,解决方案是什么呢,当然对应的就是将单例的变成多例的。
通过上网查找后在模块线程的类加上注解
@Scope("prototype")
但是加上这个注解后并没有用(并不能多例),梳理了一下问题,当我在一个单例的类中通过@Autowired自动装配时,并不能产生多例的,原因@Autowired自动装配时,在spring容器中发现这个类的实例就会装配进取,所以并没有显式的创建新的实例。所以并不能在单例中这样创建多例。
//获取Spring上下文
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
ThreadModuleA module_A = wac.getBean("threadModuleA", ThreadModuleA.class);

这是一种不依赖于servlet,不需要注入的方式。但是需要注意一点,在服务器启动时,Spring容器初始化时,不能通过以下方法获取Spring 容器。
这样的话就可以创建多例了。

下面简单的放一下代码
主线程

reportBody = new ReportBody();
            List<Task<ReportBody>> tasks = new ArrayList<Task<ReportBody>>();
            Map<String, Object> map_report = new HashMap<String, Object>();
            map_report.put("reportBody", reportBody);
            // Body
            //获取Spring上下文
            WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
            if(reportType.contains(CommonEnum.THEMIS_DATA_A.getCode())){
                map_report.put("paramsMap_base", paramsMap_base);
                //获取对象,此操作可以获取多例对象(ThreadModuleA 需要配置@Scope("prototype"))
                ThreadModuleA module_A = wac.getBean("threadModuleA", ThreadModuleA.class); 
                module_A.taskParams(map_report);
                tasks.add(module_A);
            } 
            if(reportType.contains(CommonEnum.THEMIS_DATA_B.getCode())){
                map_report.put("paramsMap_base", paramsMap_base);
                ThreadModuleB module_B = wac.getBean("threadModuleB", ThreadModuleB.class);
                module_B.taskParams(map_report);
                tasks.add(module_B);
            } 
            if(reportType.contains(CommonEnum.THEMIS_DATA_C.getCode())) {
                map_report.put("paramsMap_C", paramsMap_base);
                ThreadModuleC module_C = wac.getBean("threadModuleC", ThreadModuleC.class);
                module_C.taskParams(map_report);
                tasks.add(module_C);
            }
            if(reportType.contains(CommonEnum.THEMIS_DATA_D.getCode())){
                map_report.put("paramsMap_D", paramsMap_base);
                ThreadModuleD module_D = wac.getBean("threadModuleD", ThreadModuleD.class);
                module_D.taskParams(map_report);
                tasks.add(module_D);
            }

模块线程父类,赋值取值(其中Task继承了Callable)

public abstract class RunTask<T> implements Task<T>{
    //传入参数
    private Map<String, Object> params;

    @Override
    public void taskParams(Map<String, Object> params) {
        this.params = params;
    }

    public Map<String, Object> getParams() {
        return params;
    }

}

模块线程

@Component
@Scope(“prototype”)
public class ThreadModuleA extends RunTask{

// 日志
private static Logger logger = LoggerFactory.getLogger(ThreadModuleA.class);

@Override
public ReportBody call() throws Exception {
    // 初始化异步调用所需信息
    //获取参数
    Map<String, Object> map = this.getParams();

    return reportBody;
}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值