2017-07-25 72 views
1

1.如何將彈簧豆注入線程彈簧不會將豆注入線程

2.如何在彈簧bean內部啓動線程。

這是我的代碼。

MyThread.java

@Component 
public class MyThread implements Runnable { 

    @Autowired 
    ApplicationContext applicationContext; 

    @Autowired 
    SessionFactory sessionFactory; 

    public void run() { 

     while (true) { 
      System.out.println("Inside run()"); 
      try { 
       System.out.println("SessionFactory : " + sessionFactory); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      try { 
       Thread.sleep(10000); 

       System.out.println(Arrays.asList(applicationContext.getBeanDefinitionNames())); 

      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

    } 

} 

我從下面像類調用run方法(請建議,如果我錯了如下的appraoch調用Spring bean的內螺紋)

@Component 
public class MyServiceCreationListener implements ApplicationListener<ContextRefreshedEvent> { 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 

     if (event.getApplicationContext().getParent() == null) { 
      System.out.println("\nThread Started"); 
      Thread t = new Thread(new MyThread()); 
      t.start(); 

     } 
    } 
} 

春不執行依賴注入MyThread

+0

首先,您不應該在容器中自己啓動線程。理想情況下,你應該有一個'TaskExecutor'來傳遞任務的實例('Runnable'或'Callable')來執行。這樣你就可以使用受支持的方式使用線程和servlet容器。接下來,你應該讓你的bean'@Scope(「prototype」)'並且在啓動線程之前使用'ApplicationContext'來獲得一個實例。您現在正在Spring的範圍外創建一個新實例。 –

+0

,但你說在下面的評論中說,由於內存問題和怪異的應用程序行爲不創建新的上下文 –

+0

我在哪裏說你應該創建一個新的'ApplicationContext' ...你可以'@ Autowire'上下文到你的'MyServiceCreationListener'並使用該實例從中獲取bean。我說沒有地方你應該創造一個新的實例! –

回答

2

您的設置存在一些問題。

  1. 你不應該自己創建和管理線程,Java有很好的功能來使用它們。
  2. 你正在自己創建新的bean實例,希望Spring知道它們並注入依賴關係,這是行不通的。

Spring提供了一個抽象來執行任務,TaskExecutor。你應該配置一個並使用它來執行你的任務,而不是自己創建一個線程。

將此添加到您的@Configuration班。

@Bean 
public ThreadPoolTaskExecutor taskExecutor() { 
    return new ThreadPoolTaskExecutor(); 
} 

MyThread@Scope("prototype")進行註釋。

@Component 
@Scope("prototype") 
public class MyThread implements Runnable { ... } 

現在,你可以注入這些豆子和ApplicationContext到您的MyServiceCreationListener

@Component 
public class MyServiceCreationListener implements ApplicationListener<ContextRefreshedEvent> { 

    @Autowired 
    private ApplicationContext cox; 
    @Autowired 
    private TaskExecutor taskExecutor;   

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 

     if (event.getApplicationContext().getParent() == null) { 
      System.out.println("\nThread Started"); 
      taskExecutor.execute(ctx.getbean(MyThread.class)); 
     } 
    } 
} 

這會給你的MyThread一個預配置的,新鮮的實例並執行它在由TaskExecutor選擇Thread手。

+0

我沒有使用'@Configuration'類,那麼我應該在spring-config.xml文件中創建'ThreadPoolTask​​Executor'bean? –

+0

無論您用於配置,如果您願意,也可以是xml。 –

+0

將taskExecutor調用runnable類的run()方法嗎? –

0

您的MyThread是手動創建的,而不是通過彈簧控制器文字new Thread(new MyThread());所以春天沒有機會注入一個bean。

相反,您可以添加一個技巧,通過靜態訪問彈簧上下文,您可以從上下文獲取必需的bean(請參閱herehere)。

或者,您可以使用ThreadLocalInheritableThreadLocal來存儲要在線程中使用的必需對象。

+0

我只想在MyServiceCreationListener中啓動MyThread ....我該怎麼做? –

0

您正在創建Thread t = new Thread(new MyThread());.Spring容器不會注入依賴項,也不會維護bean的生命週期。

實施例:

@Component 
@Scope("prototype") 
public class PrintThread extends Thread{ 

    @Override 
    public void run() { 

     System.out.println(getName() + " is running"); 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(getName() + " is running"); 
    } 

} 

從彈簧上下文存取線程對象。

public class ApplicationContextUtils implements ApplicationContextAware { 
private static ApplicationContext ctx; 

private static final String USER_THREAD = "printThread"; 

    @Override 
    public void setApplicationContext(ApplicationContext appContext) 
     throws BeansException { 
    ctx = appContext; 

    } 

    public static ApplicationContext getApplicationContext() { 
    return ctx; 
    } 

    public static UserService getUserService(){return ctx.getBean(USER_THREAD);} 

} 
+0

什麼是AppConfig.class .....我沒有在我的應用程序中使用 –

+0

不要創建一個新的上下文來獲取單個bean ...您現在正在重新創建整個應用程序。除非你想要一個內存消耗,怪異的行爲應用程序,這是可以去的。 –

+0

@ M.Deinum更新了我的代碼 –