Ok, final solution for my use case will use the approach described in this answer. It would be better because it will be possible to track usages and I'll get rid of every problem I'm having with the current approach.
In that way I can do the following
@Component
public class ArtifactImpl extends AbstractGenericImpl<Artifact> {
}
@Component
public class MaterialImpl extends AbstractGenericImpl<Material> {
}
@Component
class Usage {
@Autowired ArtifactImpl foo;
@Autowired MaterialImpl bar;
}
In this way everything is checked at compile time and I got rid of Class<T>
constructor in fact I have autowiring in place (without @Qualifier) and the following test is working:
@RunWith(SpringJUnit4ClassRunner.class)
public class AutowiringTest {
@Autowired Usage test;
public void testAutowiring() {
assertThat(test.foo.getGenericType(), equalTo(Artifact.class));
assertThat(test.bar.getGenericType(), equalTo(Material.class));
}
}
Original answer
Ok, I've found out that what I'm asking will be useless because autowiring happens at runtime and so having two autowired object with different objects will lead to spring errors, i.e. this won't work:
@Configuration
class RetrieverProvider {
@Bean
Retriever<Artifact> getArtifact() {
return new RetrieverImpl<Artifact>() {};
}
@Bean
Retriever<Material> getMaterial() {
return new RetrieverImpl<Material>() {};
}
}
class InjectedAttempt {
// at injection time, i.e. runtime, type erasure prevent spring to distinguish
@Autowired Retriever<Artifact> foo; // this type
@Autowired Retriever<Material> bar; // from this type
// so it cannot perform injection by type
}
The only way to get that working is to use qualifiers in this way, but I don't like this approach, so I'll remain with xml configuration and constructor arguments.
@Configuration
class RetrieverProvider {
@Bean @Qualifier("artifact") Retriever<Artifact> getArtifact() {
return new RetrieverImpl<Artifact>() {};
}
@Bean @Qualifier("material")
Retriever<Material> getMaterial() {
return new RetrieverImpl<Material>() {};
}
}
class Injected {
@Autowired @Qualifier("artifact") Retriever<Artifact> foo;
@Autowired @Qualifier("material") Retriever<Material> bar;
}
As a side note guice has support for generic injections, maybe spring has something similar.