Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 777
Rythmic Avatar asked Sep 14 '25 20:09

Rythmic


2 Answers

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

  • Spring Reference: Chapter 8.8.1 Using AspectJ to dependency inject domain objects with Spring
  • Spring autowiring using @Configurable
like image 88
Ralph Avatar answered Sep 16 '25 11:09

Ralph


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...)

like image 45
eis Avatar answered Sep 16 '25 09:09

eis