2016-06-27 20 views
1

Ich erstelle ein Programm, das bisher etwa 12 DAO und Services hat. Die DAO's und Dienste sind in erster Linie die gleichen, also habe ich ein generisches DAO und einen Service aufgebaut, der um die 12 DAO's und Services erweitert wurde, so dass sie alle Zugang haben zum Speichern, Aktualisieren, Löschen und Finden von ById. Alles funktionierte perfekt, wenn ich verwendet nur 1 Klasse für die Prüfung (RegularUser), aber sobald ich alle Klassen über die Verlängerung der generische DAO und Dienst eingeschaltet, bekam ich diese Fehlermeldung:org.springframework.beans.factory.UnsatisfiedDependencyException: Fehler beim Erstellen Bean ... erwartet einzelne übereinstimmende Bean aber gefunden 12

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'genericServiceImpl' defined in file [C:\Users\Contronym\workspace\Glimps App\target\classes\com\glimpsmedia\app\generic\service\GenericServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type [com.glimpsmedia.app.generic.dao.GenericDao] is defined: expected single matching bean but found 12: businessCategoryDaoImpl,businessUserDaoImpl,campaignCategoryDaoImpl,campaignDaoImpl,competitorDaoImpl,followDaoImpl,friendDaoImpl,giveawayDaoImpl,glimpsDaoImpl,regularUserDaoImpl,userCategoryDaoImpl,viewDaoImpl; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.glimpsmedia.app.generic.dao.GenericDao] is defined: expected single matching bean but found 12: businessCategoryDaoImpl,businessUserDaoImpl,campaignCategoryDaoImpl,campaignDaoImpl,competitorDaoImpl,followDaoImpl,friendDaoImpl,giveawayDaoImpl,glimpsDaoImpl,regularUserDaoImpl,userCategoryDaoImpl,viewDaoImpl 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) 
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83) 
    at com.glimpsmedia.app.main.App.main(App.java:14) 
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.glimpsmedia.app.generic.dao.GenericDao] is defined: expected single matching bean but found 12: businessCategoryDaoImpl,businessUserDaoImpl,campaignCategoryDaoImpl,campaignDaoImpl,competitorDaoImpl,followDaoImpl,friendDaoImpl,giveawayDaoImpl,glimpsDaoImpl,regularUserDaoImpl,userCategoryDaoImpl,viewDaoImpl 
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1059) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:834) 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) 
    ... 15 more 

Mein generic DAO:

public class GenericDaoImpl<T> implements GenericDao<T> { 

    @Autowired 
    private SessionFactory sessionFactory; 

    private final Class<T> type; 

    public GenericDaoImpl(final Class<T> type) { 
     this.type = type; 
    } 

    public void save(final T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.save(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public void update(final T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.update(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public void delete(final T obj) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     try { 
      tx = session.beginTransaction(); 
      session.delete(obj); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

    } 

    public T findById(final long id) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = null; 
     T obj = null; 
     try { 
      tx = session.beginTransaction(); 
      obj = session.get(type, id); 
      tx.commit(); 
     } catch (HibernateException e) { 
      if(tx != null) 
       tx.rollback(); 
      e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 

     return obj; 
    } 

} 

Mein generic Service:

@Service 
@Transactional 
public class GenericServiceImpl<T> implements GenericService<T> { 

    private GenericDao<T> dao; 

    @Autowired 
    public GenericServiceImpl(GenericDao<T> dao) { 
     this.dao = dao; 
    } 

    public void save(T obj) { 
     dao.save(obj); 
    } 

    public void update(T obj) { 
     dao.update(obj); 
    } 

    public void delete(T obj) { 
     dao.delete(obj); 
    } 

    public T findById(long id) { 
     return dao.findById(id); 
    } 

} 

auch hier ist ein Beispiel für eine der DAO. Sie sind alle gleich, außer für die Klassennamen (es gibt 12 von ihnen):

@Repository("regularUserDaoImpl") 
public class RegularUserDaoImpl extends GenericDaoImpl<RegularUser> 
    implements RegularUserDao { 

    public RegularUserDaoImpl() { 
     super(RegularUser.class); 
    } 

} 

Und ein Beispiel für einen Service (auch hier gibt es 12 davon, eine für jede DAO):

@Service("regularUserServiceImpl") 
@Transactional 
public class RegularUserServiceImpl extends GenericServiceImpl<RegularUser> 
    implements RegularUserService { 

    public RegularUserServiceImpl(GenericDao<RegularUser> dao) { 
     super(dao); 
    } 

} 

Ich habe versucht, etwas zu diesem Thema zu tun, und sah etwas in Bezug auf eine @Qualifier Tag, aber ich habe keine Ahnung, wie ich es hier implementieren würde, da die @Autowired Tag in den generischen Klassen 12 verschiedene Optionen zur Auswahl haben, so dass ich nicht ' t wissen, was in @Qualifier oder wie man @Qualifier dynamisch machen.

+0

https://www.jayway.com/2013/11/03/spring-and-autowiring-of-generic-types/ Ist das wonach Sie suchen? – Compass

+0

@Compass Definitiv hilfreich bei der Erklärung, warum es nicht funktioniert, aber es löst mein Problem nicht, da ich auch einen generischen 'Service' habe, wo der' Dao' steht. Ich glaube, meine Umsetzung ist falsch. Möglicherweise müssen Sie das 'Dao' in die nicht-generischen' DaoImpl' Klassen einfügen und es dann an den generischen Dienst übergeben? Ich werde das versuchen und sehen, ob es funktioniert. –

+0

@Compass kann es nicht herausfinden ... Irgendwelche Vorschläge? –

Antwort

0

Endete, es zu reparieren. Keine Notwendigkeit für @Qualifier in Frühling 4.0 und weiter. Ich habe den Tag @Primary zu einem meiner DAO's hinzugefügt. Das Problem wurde behoben und alles funktioniert jetzt einwandfrei. Der Frühling wird aus irgendeinem Grund verwirrt, es sei denn, Sie haben @Primary über einem der DAO.

+0

Das liegt daran, dass Sie 12 verschiedene Beans haben, die 'GenericDao' implementieren; Wenn Sie 'GenericDao' injizieren, dann weiß Spring nicht, welche der 12 von Ihnen injiziert werden soll. Mit '@ Primary' geben Sie den an, den Sie injiziert haben möchten. – Jesper

+0

@Jesper Ich setze @Primary über '' RegularUserDaoImpl' ', aber immer wenn ich versuche' BusinessUserDaoImpl' oder irgendeinen anderen DAO/Dienst zu instanziieren, benutzt es die richtigen. Es wird kein 'RegularUserDao' injiziert, es sei denn, ich versuche ein' RegularUserDao' zu instanziieren. Was ist der Grund dafür? –

+0

Schauen Sie sich Roman an, er ist auf dem richtigen Weg. Wenn Sie festlegen möchten, dass 'GenericServiceImpl 'eine Superklasse für bestimmte Service-Implementierungen ist, sollten Sie keine' @ Service'-Annotation auf 'GenericServiceImpl' platzieren, da Spring diese dann direkt instanziiert. Die Annotation "@ Service" sollte nur für die spezifischen Unterklassen gelten. Es ist auch eine gute Idee, 'GenericServiceImpl' und' GenericDaoImpl' 'abstract' zu erstellen - sie sollen nur als Superklassen verwendet werden und nicht selbst instanziiert werden. – Jesper

1

Entfernen Sie @Service Annotation von GenericServiceImpl, es sagt Spring, um einen generischen Dienst mit einem generischen DAO zu erstellen, das ist wahrscheinlich nicht das, was Sie möchten. Auch ein Vorschlag: make GenericDaoImpl und GenericServiceImpl abstract, also versucht niemand sie zu instanziieren.
Und es gibt keine Notwendigkeit in @Qualifier oder @Primary.