views:

124

answers:

3

Hi guys!

I would like to know if it's possible to use Spring to resolve the dependencies of an object created manually in my program. Take a look at the following class:

public class TestClass {

   private MyDependency md;

   public TestClass() {
   }

   ...

   public void methodThaUsesMyDependency() {
      ...
      md.someMethod();
      ...
   }

}

This TestClass is not a spring bean, but needs MyDependency, that is a spring bean. Is there some way I can inject this dependency through Spring, even if I instantiate TestClass with a new operator inside my code?

Thanks

+1  A: 

See the autowire() method on the AutowireCapableBeanFactory class. If you use an ClasspathXmlApplicationContext, you can get the factory with getAutowireCapableBeanFactory()

To get the ApplicationContext, you would need to use a static singleton or other central repository, such as JNDI or a Servlet container. See DefaultLocatorFactory on how to get an instance of the ApplicationContext.

mhaller
+1  A: 

If what you need is for testing purposes, Spring has good support for the scenario that you described above.

Check out Spring Reference manual section on Testing

DJ
+1  A: 

Edit: The method I'm describing in my original answer below is the general way to accomplish DI external of the container. For your specific need - testing - I agree with DJ's answer. It's much more appropriate to use Spring's test support, for example:

@Test
@ContextConfiguration(locations = { "classpath*:**/applicationContext.xml" })
public class MyTest extends AbstractTestNGSpringContextTests {

    @Resource
    private MyDependency md;

    @Test
    public void myTest() {
            ...

While the above example is a TestNG test, there is also Junit support explained in 8.3.7.2. Context management and caching.


General approach: Annotate your class with @Configurable and utilize AspectJ load-time or compile-time weaving. See 6.8.1 in the Spring documentation on AOP for more details.

You can then annotate your instance variables with @Resource or @Autowired. Though they accomplish the same goal of dependency injection, I recommend using @Resource since it's a Java standard rather than Spring-specific.

Lastly, remember to consider using the transient keyword (or @Transient for JPA) if you plan on serializing or persisting the objects in the future. Chances are you don't want to serialize references to your DI'd repository, service, or component beans.

rcampbell
Spring can only do what you say to a bean that Spring knows about but the OP specifically says that Spring knows nothing of `TestClass` since it is manually created.
non sequitor
@non sequitor, please read the documentation I provided. It specifically states, "The spring-aspects.jar contains an annotation-driven aspect that exploits this capability to allow dependency injection of any object. The support is intended to be used **for objects created outside of the control of any container**. Domain objects often fall into this category because they are often created programmatically using the new operator, or by an ORM tool as a result of a database query."
rcampbell
AspectJ weaving is used so that you're not actually instantiating your original TestClass, but rather a byte-code modified version of TestClass which knows how to request DI from Spring.I make heavy use of this technique in my own projects, and I can assure you it works.
rcampbell