Spring 4 brings some nice improvements to how autowiring of generic types are handled. Before going into details, let’s look into the current state of affairs.

Basics

Consider the following example where you have one generic interface:

interface GenericDao<T> {
    // ...
}

And two concrete implementations of it:

@Repository
class FooDao implements GenericDao<Foo> {
    // ...
} 
@Repository
class BarDao implements GenericDao<Bar> {
    // ...
}

Now, the task is to create a FooService that autowires an instance of the FooDao class. Using current Spring versions, i.e. versions 3.x, one can either tie the implementation of the FooService class to the FooDao class:

@Service
class FooService {

    @Autowired
    private FooDao fooDao;
}

Or use the @Qualifer annotation:

@Service
class FooService {

    @Autowired
    @Qualifier("fooDao")
    private GenericDao fooDao;
}

However, the disadvantage of these implementations is that they both suffer from coupling. In the first example, the FooService implementation is tightly coupled to the FooDao class. The second example has less coupling in a way that the FooService does not know about the class that implements the GenericDao, but there is still some coupling present because the name of the FooDao bean is hardcoded in the FooService implementation. As of Spring 4 RC1, the issue SPR-9965 has been solved, which allows us to do autowiring by generic type:

@Service
class FooService {

    @Autowired
    private GenericDao<Foo> fooDao;
}

Subtle difference, the key difference is that the FooService implementation does not need any information about the implementing FooDao bean, they are completely decoupled from each other. Side note, if you attempt to use this solution in a Spring 3.x environment, you will find that it works if your application context contains a single GenericDao bean. However, you will get an exception if the application context contains two or more beans. When the generic type is not acknowledged, Spring cannot determine which bean to use:

NoUniqueBeanDefinitionException: No qualifying bean of type [GenericDao] is defined:
    expected single matching bean but found 2: barDao,fooDao

Inheritance

To further investigate the autowiring issue, one can also see how it affects inheritance. In a pre Spring 4 environment, there is a little ceremony to handle inheritance and generic types. First, a GenericService needs a constructor with the generic type:

abstract class GenericService<T> {

    private GenericDao<T> dao;

    GenericService(GenericDao<T> dao) {
        this.dao = dao;
    }

    // ...
}

Then we yet again have to tightly tie the implementation of a specific service to its specific dao:

@Service
class FooService extends GenericService<Foo> {

    @Autowired
    FooService(FooDao fooDao) {
        super(fooDao);
    }
}

Spring 4 also makes it possible to autowire generic class hierarchies. First, we can autowire a GenericDao instance to the GenericService:

abstract class GenericService<T> {

    @Autowired
    private GenericDao<T> dao;

    // ...
}

Next, we can implement the concrete FooService by just extending the GenericService with the generic type:

@Service
class FooService extends GenericService<Foo> {
}

Problem solved with less code and less coupling than before.

Spring 4 RC1

Spring Framework project lead Juergen Hoeller writes in a blog post:

Overall, this is the perfect time to give Spring Framework 4.0 an early try! We’ll make sure to incorporate your feedback in a timely fashion on our way to 4.0 GA in December.

Spring 4 RC1 is available in the Spring milestone repository. Add it to your list of Maven repositories:

<repositories>
    <repository>
        <id>org.springframework.maven.milestone</id>
        <name>Spring Milestone Repository</name>
        <url>http://maven.springframework.org/milestone/</url>
    </repository>

    <!-- more repositories -->

</repositories>

Update your Spring dependencies to version 4.0.0.RC1 accordingly:

<dependencies>
    <dependency>
        <groupid>org.springframework</groupid>
        <artifactid>spring-core</artifactid>
        <version>4.0.0.RC1</version>
    </dependency>

    <!-- more dependencies -->

</dependencies>

Update

Dec 4th, 2013: Phil Webb has published a blog post at the Spring blog titled Spring Framework 4.0 and Java Generics which further elaborates the topic.

Update 2

Dec 12th, 2013: Adrian Colyer announced the release of Spring 4.0 (which means that you should update the version number to 4.0.0.RELEASE, and that you can remove the declaration of the Spring Milestone Repository in case you used the 4.0.0.RC1 version).

Updated: