简体   繁体   English

Spring没有将bean注入线程

[英]Spring not injecting a bean into thread

1.How to inject a spring bean into thread 1.如何在线程中注入一个spring bean

2.How to start a thread inside spring bean. 2.如何在spring bean里面启动一个线程。

here is my code.这是我的代码。

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

    }

}

i am calling run method from below class like (Please suggest if i am following wrong appraoch for calling a thread inside spring bean )我正在从下面的类调用run方法(请建议我是否遵循错误的方法来调用 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();

        }
    }
}

spring is not performing dependency injection on MyThread class spring 不在MyThread类上执行依赖注入

There are a couple of things wrong with your setup.您的设置有一些问题。

  1. You shouldn't be creating and managing threads yourself, Java has nice features for that use those.你不应该自己创建和管理线程,Java 有很好的特性来使用它们。
  2. You are creating new bean instances yourself and expect Spring to know about them and inject dependencies, that isn't going to work.您自己正在创建新的 bean 实例,并希望 Spring 了解它们并注入依赖项,这是行不通的。

Spring provides an abstraction to execute tasks, the TaskExecutor . Spring 提供了一个抽象来执行任务,即TaskExecutor You should configure one and use that to execute your task not create a thread yourself.您应该配置一个并使用它来执行您的任务,而不是自己创建线程。

Add this to your @Configuration class.将此添加到您的@Configuration类。

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

Your MyThread should be annotated with @Scope("prototype") .你的MyThread应该用@Scope("prototype")注释。

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

Now you can inject these beans and an ApplicationContext into your MyServiceCreationListener现在你可以将这些 bean 和一个ApplicationContext注入你的MyServiceCreationListener

@Component
public class MyServiceCreationListener implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ApplicationContext ctx;
    @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));
        }
    }
}

This will give you a pre-configured, fresh instance of MyThread and execute it on a Thread selected by the TaskExecutor at hand.这将为您提供一个预先配置的MyThread新实例,并在手头的TaskExecutor选择的Thread上执行它。

Your MyThread is created manually rather than via spring context new Thread(new MyThread());你的 MyThread 是手动创建的,而不是通过 spring 上下文new Thread(new MyThread()); so no chance for spring to inject a bean.所以春天没有机会注入豆子。

Instead you can add a trick with static access to spring context where you can get a necessary bean from the context (see here or here ).相反,您可以添加一个对 spring 上下文进行静态访问的技巧,您可以在其中从上下文中获取必要的 bean(请参阅此处此处)。

Alternatively you can use ThreadLocal or InheritableThreadLocal to store necessary objects to be used in the thread.或者,您可以使用ThreadLocalInheritableThreadLocal来存储要在线程中使用的必要对象。

You are creating Thread t = new Thread(new MyThread());您正在创建Thread t = new Thread(new MyThread()); .Spring container will not inject the dependency and also not maintain the life cycle of bean. .Spring 容器不会注入依赖,也不会维护 bean 的生命周期。

Example :示例:

@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");
    }

}

to access the thread object from spring context.从 spring 上下文访问线程对象。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM