7

Estoy tratando de utilizar la anotación @Autowired con mi interfaz genérica Dao así:Spring 3 DI mediante la interfaz DAO genérico

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

utilizo esta interfaz en mi controlador en el seguimiento de la moda:

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

    @Autowired 
    private DaoContainer<User> userContainer; 

    // Implementation omitted for brevity 
} 

he configurado mi contexto de aplicación con el siguiente configuración

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

Esto sólo funciona partiall y, dado que Spring crea e inyecta solo una instancia de mi DaoContainer, concretamente DaoContainer. En otras palabras, si pregunto userContainer.numberOfItems(); Consigo el número de notificationContainer.numberOfItems()

que he tratado de utilizar las interfaces inflexible con motivo de la aplicación correcta de esta manera:

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

y luego usaron estas interfaces como esto:

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

Lamentablemente esto no logra 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)} 

Ahora, Estoy un poco confundido, ¿cómo debo proceder o si estoy usando múltiples Dao incluso posible? Cualquier ayuda sería muy apreciada :)

+0

No veo ninguna clase de implementación para sus interfaces. ¿Cuántos hay y cómo se ven? – skaffman

+0

No tenía implementaciones explícitas para las interfaces, ya que esperaba poder utilizar la clase de dao genérica (es decir, DaoContainer ). Pude crear implementaciones explícitas (como señaló Espen en su respuesta). Eso simplemente no parece razonable, ya que estoy tratando de aprovechar los genéricos de Java tanto como sea posible. Sin embargo, tengo DaoContainerImpl . – Peders

+0

tal vez http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/511417#511417 es una solución –

Respuesta

0

Es posible conectar automáticamente tantos frijoles como desee.

Pero cuando usa el autoenvío por tipo, puede ser solo uno de los beans de cada interfaz. Su mensaje de error dice que no tiene ningún bean disponible en el contenedor Spring de la interfaz dada.

Una solución:

Sus faltan implementaciones DAO:

@Repository 
public class NotificationContainerImpl implements NotificationContainer {} 

@Repository 
public class UserContainerImpl implements UserContainer {} 

su clase de servicio:

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

que sustituyen la anotación @Configurable con @Service. @Configurable se usa junto con AspectJ y no es lo que desea aquí. Debe usar @Component o una especialización de la misma como @Service.

Recuerde también tener todos sus componentes Spring dentro de su paquete com.organization.sample para permitir que el contenedor Spring los encuentre.

Espero que esto ayude!

2

Ok, creo que he encontrado una solución bastante razonable para este rompecabezas. Una forma de lidiar con esto sería crear interfaces e implementaciones para cada entidad en mi modelo de dominio (como señaló Espen en su respuesta anterior). Ahora, considere tener cientos de entidades y cientos de implementaciones respectivamente. Eso no se sentiría bien, ¿verdad?

He descartado fuertemente tipado sub-interfaces y estoy usando interfaz genérica en su lugar:

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

Implementación de mi interfaz DaoContainer sería algo como esto:

@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 

} 

Y por último la aplicación contexto:

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

Así que, básicamente, no pude conseguir puro genérico autocableante para trabajar, pero esta solución funciona para mí (al menos por ahora) :)

+0

Sé que este es un problema antiguo, pero su solución es bastante similar al uso de marcador interfaces como se describe en http://stackoverflow.com/questions/502994/spring-ioc-and-generic-interface-type/503011#503011. Supongo que se trata de una preferencia personal para contaminar el archivo de configuración de Spring o el árbol de Java source. –

Cuestiones relacionadas