2016-07-14 12 views
4

Ich brauche Spring-Beans zugreifen (featureService und uxService) in meinem ausführbaren Thread unten, aber sind immer null Wert für applicationContext daher könnte ich Frühling Bohnen im Innern des Runnable bekommen. Ich frage mich, ob es möglich ist, auf Frühlingsbohnen in einem Runnable zuzugreifen oder nicht? Wenn nicht, bitte schlagen Sie mir einen alternativen Ansatz vor.Zugriff auf Frühling Bohnen in ausführbarem Thread

Ich bin mit Spring 4.0.6 und Java 8

@Component 
public class UserMenuUpdateTask implements Runnable, Serializable, ApplicationContextAware { 


    private static final long serialVersionUID = 3336518785505658027L; 

    List<User>     userNamesList; 

    FeatureService    featureService; 

    UXService uxService; 

    private ApplicationContext applicationContext; 

    public UserMegaMenuUpdateTask() {} 

    public UserMegaMenuUpdateTask(List<User> userNamesList) { 
     this.userNamesList = userNamesList; 
    } 

    @Override 
    public void run() { 
     try { 
      for (User user : userNamesList) { 

        featureService = (FeatureService) applicationContext.getBean("featureService"); 
        uxService = (UxService) applicationContext.getBean("uxService");      
       //......... 
      } 
     } catch (BaseApplicationException ex) { 
      throw new BaseApplicationException(ex); 
     } 
    } 

    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 
     this.applicationContext = applicationContext; 

    } 
} 

Ich rufe die runnable wie unten

ExecutorService es = Executors.newCachedThreadPool(); 
es.execute(new UserMenuUpdateTask(activeUsers)); 
+0

Rufst du 'setApplicationContext()', bevor es ausgeführt wird? Sie sollten uns auch zeigen, wie Sie das Runnable verwenden. –

+0

@JiriTousek 'setApplicationContext()' soll von 'Spring'-Container beim Programmstart aufgerufen werden ..? Ich habe den Code für den Aufruf der Runnable aktualisiert – RanPaul

+0

Nur auf die Bohnen (Objekte), die es kennt. Du erstellst eine lokale Instanz in deinem Code, über die Spring keine Ahnung hat (Spring verwendet keine Magie, auch wenn es manchmal so scheint :) –

Antwort

1

Spring verwendet ThreadLocal die applicationContext zu speichern, aber ExecutorService schafft einen anderen Thread, in dem keine Bohnen verwaltet und/oder der BeanContext findet keine Beans.

Folgen Sie stattdessen instructions.

1

ApplicationContextAware ist eine von Spring verwendete Schnittstelle, um seinen Kontext in Beans zu setzen, die Spring selbst verwaltet (weiß davon). Da Sie die UserMenuUpdateTask selbst erstellen, weiß Spring nicht einmal über die Instanz und kann das Feld nicht festlegen.

Wenn Sie für jeden Aufruf/jeden Thread keine neue Instanz von Runnable benötigen (dh wenn UserMenuUpdateTask statuslos oder Thread-sicher ist), können Sie Spring (über Anmerkungen oder XML-Konfiguration) verwalten und verwenden die Spring-instanziierte Instanz in ExecutorService.execute().

Wenn eine neue Instanz von UserMenuUpdateTask jedes Mal benötigt wird, werden Sie stattdessen die anrufende Klasse ApplicationContextAware (unter der Annahme Instanz davon wird von Frühling), und stellen Sie den Zeiger auf Anwendungskontext in den UserMenuUpdateTask, bevor er es machen müssen zum ExecutorService.

0

Die ApplicationContextAware-Schnittstelle funktioniert nur, wenn das Objekt innerhalb der Feder instanziiert wird. Wenn Sie tun, neue UserMenuUpdateTask (activeUsers) Spring weiß nichts über dieses Objekt, daher legt es nicht ApplicationContext.

Schreiben Sie den Konstruktor ohne Parameter, setzen Sie den Umfang auf den Prototyp und holen Sie sich dieses Objekt aus dem Frühling, setzen Sie bei der nächsten Zeile activeUsers und es sollte funktionieren. Oder legen Sie die Anwendung nach der Objekterstellung manuell fest.

Auch würde ich empfehlen Sie diese Zeilen ändern

for (User user : userNamesList) { 

     featureService = (FeatureService) applicationContext.getBean("featureService"); 
     uxService = (UxService) applicationContext.getBean("uxService");      
      //......... 
     } 

zu

featureService = (FeatureService) applicationContext.getBean("featureService"); 
    uxService = (UxService) applicationContext.getBean("uxService");  

    for (User user : userNamesList) { 
     //......... 
    }