In your specific case, Spring doesn't allow to use a generic type to be wired as dependency such as :
@Autowired
public NoteController(NoteDAO noteDAO, Serializing<UserComment> serializer) {
this.noteDAO = noteDAO;
this.serializer = serializer;
}
for a very simple reason : consistency.
This dependency that you made a Spring bean with @Service
:
@Service
public class JsonSerializer<T extends Serializable> implements Serializing<T> {
/** code **/
}
can be wired into other beans.
Imagine that the beans that depend on the Serializing
instance don't use the same generic :
Serializing<UserComment>
in Foo
and Serializing<UserQuestion>
in Bar
such as :
public class Foo{
@Autowired
public Foo(NoteDAO noteDAO, Serializing<UserComment> serializer) {
this.noteDAO = noteDAO;
this.serializer = serializer;
}
}
public class Bar{
@Autowired
public Bar(NoteDAO noteDAO, Serializing<UserQuestion> serializer) {
this.noteDAO = noteDAO;
this.serializer = serializer;
}
}
Here the Serializing
object is the same but each bean declares a distinct generic on.
So it would break the type safety of the generic type.
In fact, erasure of the generics is not the real problem there as Spring (from Spring 4) owns a Resolver able to resolve the type :
behind the scenes, the new ResolvableType class provides the logic of
actually working with generic types. You can use it yourself to easily
navigate and resolve type information. Most methods on ResolvableType
will themselves return a ResolvableType
And before Spring 4 you also had other workaround to accept generic types in the bean dependencies.
The real problem is that you annotated a generic class with @Service
to make it a bean while it is an instance of this generic class that has to be configured as a bean.
So to achieve what you want to do, declare the JsonSerializer
beans that you want to instantiate in a @Configuration
class :
@Configuration
public class SerializingBeans {
@Bean
public JsonSerializer<UserComment> userCommentSerializer() {
return new JsonSerializer<UserComment>();
}
@Bean
public JsonSerializer<UserAnswer> userAnswerSerializer() {
return new JsonSerializer<UserAnswer>();
}
}
You can now wire the dependency as a generic type :
@Service
public class NoteController {
private Serializing<UserComment> userCommentSerializer;
@Autowired
public NoteController(Serializing<UserComment> serializer) {
this.userCommentSerializer = serializer;
}
}