2017-07-25 73 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更新了我的代码 –