Rythmic
Rythmic

Reputation: 829

Support for autowiring in a class not instantiated by spring (3)

I realize this should be really basic but I haven't found a second step example after Helloworld

So what I have is:

spring config xml called spring-beans.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <context:annotation-config />
    <context:component-scan base-package="org" />

</beans>

A spring context initialized class:

public static void main(String[] args) {
    // initialize Spring
    ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring-beans.xml");

    App app = (App) context.getBean("app");
    app.run();
}

Relevant details of AppImpl class:

@Component("app")
public final class AppImpl implements App{    

    // focus of question: This autowiring works
    @Autowired
    private DAO1 dao1;


    public void run() {
        //focus of question: This works as daoclass is instantiated properly                   
        obj1s = dao1.myFind();            

        badJobs = runJobs(obj1s);
    }

    private List<Obj1> runJobs(final List<Obj1> obj1s) {        
        List<Obj1> jobsGoneBad = new ArrayList<Obj1>();
        for (Obj1 next : obj1s) {

            // focus of question: usage of new keyword, thus not spring container managed?
            Job job = new JobImpl(next);
            job.run();

        }
        return jobsGoneBad;
    }    
}

Relevant details of JobImpl:

public class JobImpl implements Job {

    private Obj1 obj1;

    // focus of question: can't autowire
    @Autowired
    private DAO2 dao2;

    @Override
    public void run() {
        //focus of question: opDAO == null - not initialized by @Autowired
        Obj2 obj2 = dao2.myFind();        
    }

}

Relevant details of DAO1:

@Repository("DAO1") //Focus of question: DAO1 is a repository stereotype
public class DAO1 {

    myfind() { ...}
}

Relevant details of DAO2:

@Repository("DAO2") //Focus of question: DAO2 is a repository stereotype
public class DAO2 {        

    myfind() { ...}
}

Right, so I initialize the App through a springcontext call and then succesfully instantiate a DAO1 instance through the use of @Autowired.

Then I create an unmanaged instance of Job and want to inject "singeltonish" dependencies in that class too by using @Autowired

Both Dao classes are spring stereotypes and scanner finds them fine.

So my question is basically, how should I instantiate the job instance so that I can use @Autowired concept inside it?

If I need a globally accessible applicationcontext, how do I best introduce that?

Upvotes: 4

Views: 22310

Answers (4)

eis
eis

Reputation: 53462

Spring beans are singletons by default. However, what you need there are multiple instances, and on top of that, multiple instances created runtime.

One possibility is to use method injection for this. You'd create a container aware job factory that would request new instances from the container.

(I think it is a bit fishy that you'd need a DAO reference injected in those runtime instances... I would maybe try rethinking the logic. Why couldn't you just provide the DAO reference in a constructor argument, for example, or use it from somewhere else altogether. You could have a method in the dao that would accept a Jobs instance, or a runWith(DAO2 dao) stuff in the JobImpl that would be satisfied with a class injected elsewhere, or a JobProcessor service that would have the daos injected and would ask the relevant info from Jobs instance...)

Upvotes: 2

Nandkumar Tekale
Nandkumar Tekale

Reputation: 16158

Add @Component annotation to your JobImpl class. Add component scan for this class in xml and your autowiring will work for dao2(provide getter-setter methods).

Upvotes: 0

Ralph
Ralph

Reputation: 120781

You can use Spring Bean functionality like injection only in spring managed beans!

But you can use the @Configurable Annotation, but this requires that you use REAL AspectJ. If a class is annotated by @Configurable (and you use AspectJ) then you can use Springs Injection Annotations even if this class is created by a normal new.

@See

Upvotes: 5

Ben Thurley
Ben Thurley

Reputation: 7141

@Autowired isn't working because your JobImpl object isn't managed by spring so it never has a chance to inject it. Spring managed beans are those where instances are created during component scan or in XML definition. JobImpl in your case is being instantiated as a normal Java object.

One solution would be to replace the auto-wiring with a manual lookup in the spring context.

private DAO2 dao2 = SpringApplicationContext.getApplicationContext ().getBean (DAO2.class);

@Autowired is working in @AppImpl because it's annotated as @Component. This flags it up for spring during its classpath scan where it will create an instance of this class and perform any autowiring/injections.

Upvotes: 2

Related Questions