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:
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...}
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>
'autowire' your Repository in this way:
@Autowired@Qualifier("someNodeRep")Repository<SomeNode> someNodeRepository;
@Autowired@Qualifier("otherNodeRep")Repository<OtherNode> otherNodeRepository;