2016-03-30 3 views
2

Ich muss Klassen finden, die nur eine bestimmte Schnittstelle in meiner Spring Boot-App implementiert. Das Problem, dem ich gegenüberstehe, ist, dass der ClassPathBeanDefinitionScanner Klassen zurückgibt, die auch die "erweiterten" Subschnittstellen implementieren.Suchen Sie einzelne Klassen, die bestimmte Schnittstellen implementieren, aber erweiterte Schnittstellenunterimplementierungen mit Spring Framework ausschließen.

Beispiel:

public interface A {} 

public interface B extends A {} 
public interface C extends A {} 
public interface D extends A {} 

public interface E extends B {} 
public interface F extends B {} 
public interface G extends B {} 
public interface H extends B {} 
public interface I extends B {} 
public interface J extends B {} 

hier ist der Code, den ich bisher bin mit:

 BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry(); 
     ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr); 

     TypeFilter tf_include_1 = new AssignableTypeFilter(E.class); 

     TypeFilter tf_exculude1 = new AssignableTypeFilter(C.class); 
     TypeFilter tf_exculude2 = new AssignableTypeFilter(D.class); 

     s.addIncludeFilter(tf_include_1); 

     s.addExcludeFilter(tf_exculude1); 
     s.addExcludeFilter(tf_exculude2); 

     s.setIncludeAnnotationConfig(false); 

//  s.resetFilters(false); 
     s.scan("edu.university.ServiceLayer.*"); 


     System.out.println("Printing all classes that implement the E"); 
     String[] beans = bdr.getBeanDefinitionNames(); 
     for (String string : beans) { 
      System.out.println(string); 
     } 

Jetzt ist das Ergebnis, dass die das Array String „Bohnen“ enthält alle anderen Klassen, wie F , G, H, I, J usw.

Wie kann ich meinen TypeFitler so konstruieren, dass nur die ausgewählte Klasse zurückgegeben wird, die nur die angegebene Schnittstelle implementiert, dh alle Implementierungen, die die Anwendung ausführen, ausfiltert erweiterte Schnittstellen. wie B außer der Klasse E.

Hier ist der Code, der für mich nach dem Ändern des Standardkonstruktors von ClassPathBeanDefinitionScanner zu ClassPathBeanDefinitionScanner (bdr, false) wie der Benutzer @Holger vorgeschlagen funktioniert.

 BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry(); 
     ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr, false); 

     TypeFilter tf_include_1 = new AssignableTypeFilter(E.class); 


     s.resetFilters(false);  

     s.addIncludeFilter(tf_include_1); 

     s.setIncludeAnnotationConfig(false); 

     s.scan("edu.university.ServiceLayer.*"); 


     System.out.println("Printing all classes that implement the E"); 
     String[] beans = bdr.getBeanDefinitionNames(); 
     for (String string : beans) { 
      System.out.println(string); 
     } 

Bitte beachten Sie, dass resetFilters wurde kommentiert und seine die Reihenfolge auch

+2

Warum brauchen Sie das? Von einer OO-Perspektive implementieren sie alle die Schnittstelle, wenn Sie das nicht wollen, dann lassen Sie die anderen Schnittstellen die Schnittstelle in erster Linie nicht erweitern ... –

+0

erstellen Sie eine leere 'Schnittstelle OnlyA erweitert A {}' und implementieren Sie es in interessierter Bean, dann suche nach 'OnlyA' anstatt nach' A'. –

+0

@M. Deinum gut ich habe das Strategie-Pattern zusammen mit dem Template-Pattern verwendet, um das Service-Modell in meiner App zu implementieren. Das hat mir viel Tipparbeit erspart, aber jetzt muss ich eine bestimmte Schnittstelle finden, da sie sich alle gegenseitig erweitern. Im Grunde ist das die Antwort auf Ihre Frage, warum ich das brauche. Ich hatte gehofft, dass ich den TypeFilter in einer bestimmten Weise konstruieren kann, die mir nur diese eine Schnittstelle bringt. – Tito

Antwort

2

Keiner der Typen C, D, F, G, H, I, J zuordenbar E wie sie geändert worden ist, sind keine Subtypen von E, also sollte ein einfacher Einschlussfilter new AssignableTypeFilter(E.class) die Arbeit machen.

Ihr Problem stammt von der Verwendung des new ClassPathBeanDefinitionScanner(bdr) Konstruktors, der den Scanner mit Standardfiltern initialisiert, wie Sie in the source code sehen können. Während ein Typ mit allen Ausschlussfiltern verglichen wird, reicht ein einziger übereinstimmender Einschlussfilter aus, damit er im Ergebnis angezeigt wird. Sie wollen also sicher keinen anderen, möglicherweise widersprüchlichen Einschlussfilter.

Also die Lösung ist stattdessen den Konstruktor new ClassPathBeanDefinitionScanner(bdr, false) zu verwenden.

Verwandte Themen