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);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM