Is Spring @autowired not meant for non-singleton containers?

pulkitsinghal picture pulkitsinghal · Jan 1, 2014 · Viewed 45.6k times · Source

I have a MyTask class which implements Runnable and there can be many such objects instantiated at any given moment. There are certain properties that I would like to autowire into MyTask class.

But I think that if I mark MyTask with @Component then it will become a spring-managed singleton correct? That's not what I want, I need many independent instances of this class to be run by a TaskExecutor.

So my question(s):

  • a) Am I fundamentally wrong in my understanding of @Component annotation? Does it NOT make MyTask into a spring-managed singleton?
  • b) Is there some other annotation I should use so that spring detects @Autowired and injects the property?
  • c) Is spring autowiring not meant for non-singleton containers/classes like MyTask?

Update # 1 - These don't work:

public class MyTask implements Runnable { // I want this class to be non-singleton
    @Autowired
    public SomeSpecialSpringConfiguredConnectionClass blah; // this is the singleton bean that should be injected
    @Override
    public void run() {
        // BLAH IS NULL, this shouldn't be NULL, that is not what I want
        // which makes sense considering Spring never knew it had to work
        // on this class
    }
}

@Component
public class MyTask implements Runnable { // I want this class to be non-singleton
    @Autowired
    public SomeSpecialSpringConfiguredConnectionClass blah; // this is the singleton bean that should be injected
    @Override
    public void run() {
        // this works BUT now MyTask is singleton :(
    }
}

@Component
@Scope("prototype")
public class MyTask implements Runnable { // I want this class to be non-singleton
    @Autowired
    public SomeSpecialSpringConfiguredConnectionClass blah; // this is the singleton bean that should be injected
    @Override
    public void run() {
        // BLAH IS NULL, again ... this shouldn't be NULL, that is not what I want
    }
}

Update # 2 - While waiting for some more suggestions on how to do it the easy way, I'm looking into: Using AspectJ to dependency inject domain objects with Spring as an alternative.

Answer

Septem picture Septem · Jan 2, 2014

first, beans declared with @Component and picked up by spring component scan will become a spring-managed singleton by default.

I have no idea how you use MyTask, but it is overkilled to use AspectJ in your situation, and it does not make much sense to declare MyTask as a spring-managed bean. another way of doing this will be:

  1. define MyTask as a plain java class and add a constructor to initialize the dependency blah

  2. autowire blah in where you use MyTask, and instantiate a MyTask object every time you want to execute a task as follow:

    //autowire the dependency of MyTask in another spring bean with default singleton scope
    @Autowired private SomeSpecialSpringConfiguredConnectionClass blah
    //create task and wire the blah yourself
    executor.submit(new MyTask(blah))