7

Ich versuche @Autowired Annotation mit meiner generic Dao-Schnittstelle wie folgt zu verwenden:Frühling 3 DI generische DAO-Schnittstelle

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

ich diese Schnittstelle in meinem Controller verwende in folgenden Weise:

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

    @Autowired 
    private DaoContainer<User> userContainer; 

    // Implementation omitted for brevity 
} 

ich habe meinen Anwendungskontext mit folgenden Konfiguration

konfiguriere
<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 /> 

Das funktioniert nur partiall y, da Spring nur eine Instanz meines DaoContainers, nämlich DaoContainer, erstellt und injiziert. Mit anderen Worten, wenn ich userContainer.numberOfItems() frage; Ich erhalte die Anzahl der notificationContainer.numberOfItems()

Ich habe versucht, stark typisierte Schnittstellen zu verwenden, um die korrekte Umsetzung wie folgt zu markieren:

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

und verwendet dann diese Schnittstellen wie folgt aus:

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

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)} 

,:

versagt Leider dies BeanCreationException Ich bin ein wenig verwirrt, wie ich vorgehen soll oder mehrere Dao's sogar möglich benutze. Jede Hilfe würde sehr geschätzt werden :)

+0

Ich sehe keine Implementierungsklassen für Ihre Schnittstellen. Wie viele gibt es und wie sehen sie aus? – skaffman

+0

Ich hatte keine expliziten Implementierungen für die Schnittstellen, da ich gehofft hatte, ich könnte generische Dao-Klasse verwenden (d. H. DaoContainer ). Ich könnte explizite Implementierungen erstellen (wie Espen in seiner Antwort darauf hingewiesen hat). Das fühlt sich einfach nicht an, da ich versuche Java-Generika so gut wie möglich zu nutzen. Allerdings habe ich DaoContainerImpl . – Peders

+0

vielleicht http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/511417#511417 ist eine Lösung –

Antwort

0

Es ist möglich, so viele Bohnen wie Sie möchten autowire.

Aber wenn Sie Autowiring nach Typ verwenden, kann es nur einer der Bean jeder Schnittstelle sein. Ihre Fehlermeldung besagt, dass im Spring-Container der angegebenen Schnittstelle keine Bean verfügbar ist.

Eine Lösung:

Ihre fehlende DAO-Implementierungen:

@Repository 
public class NotificationContainerImpl implements NotificationContainer {} 

@Repository 
public class UserContainerImpl implements UserContainer {} 

Ihre Serviceklasse:

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

Ich ersetzte die @Configurable Annotation mit @Service. @Configurable wird zusammen mit AspectJ verwendet und ist nicht, was Sie hier wollen. Sie müssen @Component oder eine Spezialisierung davon wie @Service verwenden.

Denken Sie auch daran, alle Federkomponenten in Ihrem com.organization.sample-Paket zu haben, damit der Spring-Container sie finden kann.

Ich hoffe, das hilft!

2

Ok, ich denke, ich habe eine ziemlich vernünftige Lösung für dieses Puzzle gefunden. Eine Möglichkeit, dies zu tun, wäre die Erstellung von Schnittstellen und Implementierungen für jede Entität in meinem Domänenmodell (wie Espen in seiner Antwort bereits erwähnte). Betrachten wir nun Hunderte von Entitäten bzw. Hunderte von Implementierungen. Das würde sich nicht richtig anfühlen, oder?

Ich habe stark typisierte Unter Schnittstellen verworfen, und ich bin mit generische Schnittstelle statt:

@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 
} 

Implementierung für meine DaoContainer Schnittstelle würde wie folgt aussehen:

@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 

} 

Und schließlich Anwendung Kontext:

<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> 

Also im Grunde konnte ich nicht bekommen pure generic autowiring zu arbeiten, aber diese Lösung funktioniert für mich (zumindest für jetzt) ​​:)

+0

Ich weiß, das ist ein altes Problem, aber Ihre Lösung ist ziemlich ähnlich wie die Verwendung von Marker Schnittstellen wie in http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/503011#503011 beschrieben. Ich nehme an, es liegt an einer persönlichen Vorliebe, entweder die Spring-Konfigurationsdatei oder den Java-Quellbaum zu verschmutzen. –

Verwandte Themen