Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring 4.2.4. Autowiring list of extended generic interfaces

Tags:

java

spring

@Autowired
private List<WalletService<Wallet>> walletServices; //Doesn't work

@Autowired
private List<WalletService> walletServices; //Everything is fine

Assume we have:

interface A<T extends W>;
interface B extends A<W1>;
interface C extends A<W2> ;
class W1 extends W;
class W2 extends W;

I know it is possible to inject a list of A or specific A. Can I inject a list of A to avoid an explicit cast from List<A> to List<A<W>>? Now, when I try some i get org.springframework.beans.factory.NoSuchBeanDefinitionException

I think this feature is necessary to implementation a hierarchy of classes like this:

interface WalletService<T exends Wallet>
interface TradeWalletService extends WalletService<TradeWallet>
interface PersonalWalletService extends WalletService<PersonalWallet>

Maybe I'm missing something. Thanks in advance for your reply!

like image 466
DmRomantsov Avatar asked Mar 02 '16 14:03

DmRomantsov


1 Answers

The root cause comes from the generics definition in Java, so that WalletService<TradeWallet> is not a subclass of WalletService<Wallet>, therefore Spring cannot match the beans. On of the solutions could be using upper bounded wildcards:

private List<WalletService<? extends Wallet>> walletServices;

There is also an alternative, which is error-prone and has side effects. If you annotate your WalletService so that Spring creates a proxy object for it, both WalletService<TradeWallet> and WalletService<PersonalWallet> will be wrapped into proxy objects and for the outer world both look like WalletService w/o any generics information. This causes problems as soon as you want to inject, say, WalletService<TradeWallet> and Spring will fail as both proxied object match this bean definition.

like image 197
xwandi Avatar answered Nov 03 '22 20:11

xwandi