7

J'essaie d'utiliser l'annotation @Autowired avec mon interface générique Dao comme ceci:Spring 3 DI en utilisant l'interface générique DAO

public interface DaoContainer<E extends DomainObject> { 
    public int numberOfItems(); 
    // Other methods omitted for brevity 
} 

J'utilise cette interface dans mon contrôleur de manière suivante:

@Configurable 
public class HelloWorld { 
    @Autowired 
    private DaoContainer<Notification> notificationContainer; 

    @Autowired 
    private DaoContainer<User> userContainer; 

    // Implementation omitted for brevity 
} 

J'ai configuré mon contexte d'application avec la configuration suivante

<context:spring-configured /> 
<context:component-scan base-package="com.organization.sample"> 
<context:exclude-filter expression="org.springframework.stereotype.Controller" 
    type="annotation" /> 
</context:component-scan> 
<tx:annotation-driven /> 

Cela ne fonctionne que partiall y, puisque Spring crée et injecte seulement une instance de mon DaoContainer, à savoir DaoContainer. En d'autres termes, si je demande userContainer.numberOfItems(); Je reçois le nombre de notificationContainer.numberOfItems()

J'ai essayé d'utiliser des interfaces fortement typées pour marquer la mise en œuvre correcte comme ceci:

public interface NotificationContainer extends DaoContainer<Notification> { } 
public interface UserContainer extends DaoContainer<User> { } 

Et puis utilisé ces interfaces comme ceci:

@Configurable 
public class HelloWorld { 
    @Autowired 
    private NotificationContainer notificationContainer; 
    @Autowired 
    private UserContainer userContainer; 
    // Implementation omitted... 
} 

Malheureusement, cela ne parvient pas à BeanCreationException:

org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.organization.sample.dao.NotificationContainer com.organization.sample.HelloWorld.notificationContainer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.organization.sample.NotificationContainer] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 

maintenant, Je suis un peu confus comment devrais-je procéder ou utilise plusieurs Dao même possible. Toute aide serait grandement appréciée :)

+0

Je ne vois aucune classe d'implémentation pour vos interfaces. Combien y en a-t-il et à quoi ressemblent-ils? – skaffman

+0

Je n'avais pas d'implémentations explicites pour les interfaces, puisque j'espérais pouvoir utiliser la classe dao générique (c'est-à-dire DaoContainer ). Je pourrais créer des implémentations explicites (comme Espen l'a souligné dans sa réponse). Cela ne me semble pas raisonnable, puisque j'essaie de tirer le meilleur parti des génériques Java. Cependant, j'ai DaoContainerImpl . – Peders

+0

peut-être http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/511417#511417 est une solution –

Répondre

0

Il est possible d'autowire autant de bean que vous le souhaitez. Mais lorsque vous utilisez autowiring par type, il peut s'agir d'un seul bean de chaque interface. Votre message d'erreur indique que vous n'avez aucun bean disponible dans le conteneur Spring de l'interface donnée.

Une solution:

Vos implémentations manquantes: DAO de

@Repository 
public class NotificationContainerImpl implements NotificationContainer {} 

@Repository 
public class UserContainerImpl implements UserContainer {} 

Votre classe de service:

@Service 
public class HelloWorld { 
    @Autowired 
    private NotificationContainer notificationContainer; 
    @Autowired 
    private UserContainer userContainer; 
    // Implementation omitted... 
} 

j'ai remplacé l'annotation @Configurable avec @Service. @Configurable est utilisé avec AspectJ et n'est pas ce que vous voulez ici. Vous devez utiliser @Component ou une spécialisation de celui-ci comme @Service.

Rappelez-vous aussi d'avoir tous vos composants de printemps dans votre paquet com.organization.sample pour permettre au réservoir de printemps pour les trouver.

J'espère que cela aide!

2

Ok, je pense que je l'ai trouvé une solution assez raisonnable pour ce casse-tête. Une façon de traiter ce serait de créer l'interface et les mises en œuvre pour chaque entité dans mon modèle de domaine (comme Espen a souligné dans sa réponse précédente). Maintenant, pensez à avoir des centaines d'entités et respectivement des centaines d'implémentations. Ce ne serait pas bien, n'est-ce pas?

J'ai rejetai fortement typé sous-interfaces et j'utilise l'interface générique à la place:

@Service // Using @Service annotation instead @Configurable as Espen pointed out 
public class HelloWorld { 
    @Autowired 
    private DaoContainer<Notification> notificationContainer; 

    @Autowired 
    private DaoContainer<User> userContainer; 

    // Implementation omitted 
} 

mise en œuvre pour mon interface DaoContainer ressemblerait à quelque chose comme ceci:

@Repository 
public class DaoContainerImpl<E extends DomainObject> implements DaoContainer<E> { 

    // This is something I need in my application logic 
    protected Class<E> type; 

    public int getNumberOfItems() { 
     // implementation omitted 
    } 
    // getters and setters for fields omitted 

} 

Et enfin l'application contexte:

<context:spring-configured /> 
<context:component-scan base-package="com.organization.sample"> 
<context:exclude-filter expression="org.springframework.stereotype.Controller" 
    type="annotation" /> 
</context:component-scan> 

<bean class="com.organization.sample.dao.DaoContainerImpl" id="userContainer"> 
    <property name="type" value="com.organization.sample.domain.DiaryUser" /> 
</bean> 
<bean class="com.organization.sample.dao.DaoContainerImpl" id="notificationContainer"> 
    <property name="type" value="com.organization.sample.domain.DiaryNotification" /> 
</bean> 

donc, fondamentalement, je ne pouvais pas purement générique autowiring pour fonctionner, mais cette solution fonctionne pour moi (au moins pour l'instant) :)

+0

Je sais que c'est un vieux problème, mais votre solution est assez similaire à l'aide de marqueur interfaces comme décrit dans http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/503011#503011. Je suppose qu'il s'agit d'une préférence personnelle pour polluer le fichier de configuration Spring ou l'arborescence source Java. –

Questions connexes