Get spring bean via context using generic Get spring bean via context using generic spring spring

Get spring bean via context using generic


You can do something like this:

String[] beanNamesForType = ctx.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, node.getClass()));// If you expect several beans of the same generic type then extract them as you wish. Otherwise, just take the firstRepository<T> repository = (Repository<T>) ctx.getBean(beanNamesForType[0]);


If you could be sure that for every concrete subclass of Node (say SomeNode), every object of type SomeNode will be an actual SomeNode and not a subclass or a proxy, it would be easy. Just use a convention for the repository name (say SomeNodeRepository) and it would be trivial :

Repository<T> repository = ctx.getBean(node.getClass().getSimpleName()        + "Repository", Repository.class);

But you know that there's a high risk of getting a subclass or proxy ...

So you can try to have each Node subclass to implement a nameForRepo method :

class Node {    ...    abstract String getNameForRepo();}

and then in the subclasses

class SomeNode {    static private final nameForRepo = "SomeNode";    ...    String getNameForRepo() {        return nameForRepo;    }}

That way, even if you get a proxy or subclass, you will be able to do :

public <T extends Node> T saveNode(T node) {    Repository<T> repository = ctx.getBean(node.getNameForRepository()            + "Repository", Repository.class);    return repository.save(node);}

Alternatively, the method could directly return the repository name.


If I understand well, you want to get instance of bean with Repository class and different generic type?

I'm afraide you don't have the dynamic way with spring, but I have a work around solution:

  1. Your generic type should be a field in your class, you must have a constructor in your Repository class for setting your generic type, your Repository class should be like this:

    public class Repository<T>{ Class<T> nodeClass; public Repository(Class<?> clazz){ this.nodeClass = clazz; } // your codes...}

  2. declare a Repository bean for each Node, let's say you have Repository and Repository, if you are using xml configuration, you need to add:

    <bean id="someNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.SomeNode</value> </constructor-arg></bean><bean id="otherNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.OtherNode</value> </constructor-arg></bean>

  3. 'autowire' your Repository in this way:

    @Autowired@Qualifier("someNodeRep")Repository<SomeNode> someNodeRepository;

    @Autowired@Qualifier("otherNodeRep")Repository<OtherNode> otherNodeRepository;