Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring not injecting a bean into thread

1.How to inject a spring bean into thread

2.How to start a thread inside 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 )

@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

like image 676
suhas_n Avatar asked Jul 25 '17 08:07

suhas_n


People also ask

Can you inject a bean into an object in spring?

In a Spring application, injecting one bean into another bean is very common. However, sometimes it's desirable to inject a bean into an ordinary object. For instance, we may want to obtain references to services from within an entity object. Fortunately, achieving that isn't as hard as it might look.

Why myprototypebean can't be injected into mysingletonbean?

The problem is: spring container creates the singleton bean MySingletonBean only once, and thus only gets one opportunity to inject the dependencies into it. The container cannot provide MySingletonBean with a new instance of MyPrototypeBean every time one is needed.

When method student () is invoked by spring to create Bean?

When method student () is invoked by Spring to create its bean, it autowires the subject based on the type and satisfies its dependency. Let us verify it using the JUnit test.

How do I inject a bean into an unmanaged object?

To inject a bean into an unmanaged object, we must rely on the AnnotationBeanConfigurerAspect class provided in the spring-aspects.jar. Since this is a pre-compiled aspect, we would need to add the containing artifact to the plugin configuration.


1 Answers

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.
  2. You are creating new bean instances yourself and expect Spring to know about them and inject dependencies, that isn't going to work.

Spring provides an abstraction to execute tasks, the TaskExecutor. You should configure one and use that to execute your task not create a thread yourself.

Add this to your @Configuration class.

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

Your MyThread should be annotated with @Scope("prototype").

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

Now you can inject these beans and an ApplicationContext into your 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.

like image 149
M. Deinum Avatar answered Nov 03 '22 10:11

M. Deinum