Java IoC containers and classpath scanning (or what I’ve been looking for from .NET for months)


Frustrated with the typical way I saw IoC used in Java where every example I found involved thousands of lines of XML
and/or Java code to configure Java beans or components.  This is very different than IoC typically used in .NET where most IoC containers allow
you to “autowire” in their terminology up every class in an assembly with a couple of lines of code.  Having been coding in that fashion
for several years in .NET I was dismayed when none of my fellow Java coders that I worked with or knew personally had any concept
of the equivalent functionality, and instead informed me the IDE would be my help in maintaining these massive XML files.

Not content with their answers I burrowed into Spring, Guice and PicoContainer docs and found “classpath scanning” which is roughly
equivalent to “autowire” in .NET. Below is an example of this in Spring 3:

MyStuff.java (my main class note his has 2 dependencies which you can view on my github repo)

package org.foo;</p>

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service //one way of marking this as a component to register
public class MyStuff {
    private final DependencyWithNoInterface first;
    private final DependencyInterface second;

    @Autowired //tells spring which constructor to use for it’s dependencies
    public MyStuff(DependencyWithNoInterface first, DependencyInterface second) {

        this.first = first;
        this.second = second;
    }

    public void run(){
        System.out.println(“foo me”);
        first.foo();
        second.superFoo();
    }
} </div> </div>

appContext.xml (seems you still need some 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-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd”
>
     <context:component-scan base-package=“org.foo”/>
</beans>

Application.java (the initialization)

package org.foo;</p>

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {
    public static void main(String args[]){
        ApplicationContext ctx =   new ClassPathXmlApplicationContext(“appContext.xml”); //the IoC container
        MyStuff stff = ctx.getBean(MyStuff.class); //my fully injected class
        stff.run();
    }
} </div> </div>

 

 

Now I’m sure for the .NET developers familiar with StructureMap, Windsor, Autofac, etc this is completely unimpressive. I’m also sure there are Java developers that are somewhat unimpressed with this but for reasons that involve holding onto giant configuration artifacts. Manual IoC component registration falls where hand writing SQL for trivial data access does for me, extra repetitive work that has been solved years ago.

Edit:

It appears you can forgo XML as well in your main class use a different Application context and add the refresh and scan lines

package org.foo; </p>

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String args[]){
        AnnotationConfigApplicationContext ctx =   new AnnotationConfigApplicationContext(); 
        ctx.scan("org.foo"); //scans the org.foo package
        ctx.refresh(); //needed to load them for some reason
        MyStuff stff = ctx.getBean(MyStuff.class);
        stff.run();
    }
} </div>

Anti-Pattern: Too much of your application is about interacting with external resources