zoukankan      html  css  js  c++  java
  • Spring注解【非单例】

    花了至少一整天的时间解决了这个问题,必须记录这个纠结的过程,问题不可怕,思路很绕弯。

    为了能说清楚自己的问题,我都用例子来模拟。

    我有一个类MyThread是这样的:

    1 @Service
    2 public class MyThread extends Thread {
    3 @Autowired
    4 MyService myService;
    5 ......
    6 }

    在主线程中有这样一个调用:

    1 @Autowired
    2 MyThread myThread;
    3 ......
    4 public void invoke{
    5   if(condition){
    6     myThread.start();
    7   }  
    8 }
    9 ......

    我的invoke存在一个循环调用,此时遇到了第一个问题!

    问题一:抛出java.lang.IllegalThreadStateException。

    问题一的解决:

    1 //@Autowired
    2 //MyThread myThread;
    3 ......
    4 public void invoke {
    5   if(condition){
    6 //myThread.start();
    6 MyThread myThread = new MyThread(); 7 myThread.start(); 8 } 9 }

    引发的新的问题!

    问题二:我用了Spring注解,用new的话无法用注解实现注入,所以myThread中的myService对象抛出空指针。

    问题二的解决:放弃了MyThread类,新写了一个类,开始绕弯。

    1 @Service
    2 public class MyRunable implements Runnable {
    3   @Autowired
    4   MyService myService;
    5   ......
    6 }

    相应的,修改主线程中的调用。

     1  //@Autowired
     2  //MyThread myThread;
     3  @Autowired
     4  MyRunnable myRunnable;
     5  ......
     6  public void invoke{
     7    if(condition){
     8      //MyThread myThread = new MyThread();
     9      //myThread.start();
    10      Thread t = new Thread(myRunnable);
    11      t.start();
    12    }  
    13  }
    14  ......

    又遇到了新的问题!

    我需要对myRunnable线程命名。即在invoke方法中增加这么一行:

    1 ......
    2 myRunnable.setName(name);//增加的一行
    3 Thread t = new Thread(myRunnable);
    4 ......

    问题三:后面命名的myRunnable线程名称竟然覆盖前面的命名。

    打印myRunnable对象,很容易判断出来这个对象是单例模式,所以每次改动都会影响以前的调用。

    查了Spring的相关资料,得到结论,Spring默认管理类的模式就是“单例模式”,我需要改成非单例的。

    尝试改动一:

    1 //增加了对象使用创建模式的注解
    2 @Service
    3 @Scope("prototype")
    4 public class MyRunable implements Runnable {
    5   @Autowired
    6   MyService myService;
    7   ......
    8 }

    运行,问题依旧。然后就卡住了,甚至评估放弃Spring?一路new下去得了……

    直到某一刻灵光闪现,发现虽然现在MyRunnble是非单例模式,但是在invoke的那个类中,Spring只在加载这个类时初始化了一个MyRunnable对象啊……

    问题三的解决:

     1    //@Autowired
     2    //MyThread myThread;
     3    //@Autowired
     4    //MyRunnable myRunnable;
     5    ......
     6    public void invoke{
     7      if(condition){
     8        //MyThread myThread = new MyThread();
     9        //myThread.start();
    10        MyRunnable myRunnable = SpringContextUtil.getApplicationContext().getBean("myRunnable",MyRunnable.class);
    11        Thread t = new Thread(myRunnable);
    12        t.start();
    13     }  
    14   }
    15   ......

    这一步需要声明的是SpringContextUtil类有时间需要单独写一篇,先理解原理,就是每次从Spring容器中生成一个全新[scope("prototype")]的对象。

    到这里,问题全部解决了……等等!

    感觉MyThread类被抛弃好无辜啊!最终改成了这个样子的:

    1 MyThread myThread = SpringContextUtil.getApplicationContext().getBean("myThread", MyThread.class);
  • 相关阅读:
    Flask 【第三篇】使用DBUtils实现数据库连接池和蓝图
    Flask 【第二篇】Flask基础
    Flask 【第一篇】Flask简介
    Django 【第二十五篇】Django admin源码解析
    Django 【第二十四篇】Django admin简单使用
    Django 【第二十三篇】优化查询
    Django 【第二十二篇】ModelForm
    Django 【第二十一篇】中介模型以及优化查询以及CBV模式
    Django 【第二十篇】后端CORS解决跨域问题
    查询续与ajax
  • 原文地址:https://www.cnblogs.com/yoyotl/p/5261927.html
Copyright © 2011-2022 走看看