2016-09-06 5 views
1

In meinem ApplicationContext habe ich mehrere Beans im selben Stil erstellt. Also habe ich eine Menge von doppeltem Code, der eine FactoryBean für jede dieser Bohnen schreibt. Diese Beans haben eine gemeinsame Basis und implementieren alle eine spezielle Schnittstelle.Wie erstellt man eine Bohne nach Typ im Frühling?

Ich möchte alle diese Bean-Erstellung zu einer Fabrik verschieben. Das würde man eine Methode wie diese

<T extends CommonInterface> T createInstance(Class<T> clazz); 

zu bieten haben Dort konnte ich all die Instanziierung, die erforderlich sind einer meiner besonderen Bohnen zu erstellen.

Meine Implementierung würde durch die Feder für

@Autowired 
private MyCommonInterfaceImplementation impl; 

auf diese Weise

createInstance(MyCommonInterfaceImplementation.class) 

Bisher habe ich bei BeanFactory und FactoryBean sah genannt werden, scheinen beide nicht zu Ich suche.

Irgendwelche Vorschläge?

+0

Warum verwenden Sie nicht die '@ Component' Annotation? –

+0

@MartinFrey, wie hilft die Komponentenanmerkung in diesem Fall? Vielleicht bin ich völlig verständnis Frage, aber in diesem Fall ich diese Fall Annotation ist keine Lösung –

Antwort

1

warum nicht @bean

@Bean 
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){ 
    return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class); 
} 

//should autowire here 
@Autowired 
private MyCommonInterfaceImplementation impl; 
+0

OK, es ist weit besser als die Umsetzung jedes Mal ein FactoryBean. Aber ich habe etwas über 30 Bohnen, die zu 30 @Bean-Methoden führen, die das Gleiche tun. Die Möglichkeit, eine Bean nach Klasse zu erstellen, wäre eine große Hilfe. – mibutec

0

Ab Frühling 4.3 Sie nicht mehr Ihre Bean-Klassen mit Anmerkungen versehen haben verwenden und Sie können lassen Sie sie über eine componentscan instanziert werden.

@Configuration @ComponentScan( value = "some.package.path", includeFilters = { @Filter(type = ASSIGNABLE_TYPE, value = { MyClass1.class, MyClass2.class, MyClass3.class }) })

Dies schafft tatsächlich Bohnen für die drei Klassen dort aufgelistet. Das Beispiel sollte auch ohne Filter funktionieren (alles im Paket wird zu einer Bean). Dies funktioniert, solange die Klassen einen einzelnen Konstruktor haben, der zum Autowirfen verwendet werden kann. Ich glaube nicht, dass es möglich ist, für alle Implementierungen einer bestimmten Schnittstelle zu filtern und dann eine Bean zu registrieren.

Um dies zu tun, könnten Sie etwas mit einem ContextListener und z. Verwenden Sie reflection, um herauszufinden, welche Klassen instanziiert werden, und verwenden Sie dann context.autowire (..), um Abhängigkeiten von Ihrem Kontext einzufügen. Ein bisschen hacky, aber es könnte funktionieren.

@Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); MyClass bean = context .getAutowireCapableBeanFactory() .autowire(MyClass.class, Autowire.BY_NAME.value(), true); ... }

Das läßt immer noch das Problem, wie die Bohne im Kontext natürlich registriert zu bekommen.

Sie können die Antwort möglicherweise auch an this SO question anpassen, wie programmgesteuert Bohnen hinzugefügt werden.

1

Grundsätzlich benötigen Sie die Annotation @Bean auf einer "Fabrik" nur, wenn Sie während der Erstellung einer Bean eine spezielle Handhabung benötigen.

Wenn alles @Autowired entweder durch Setter, Felder oder einen Konstruktor sein kann und während der Initialisierung nichts an einer Bean vorgenommen werden muss, können Sie einfach die Annotation @Component für jede Implementierung Ihrer Schnittstelle deklarieren. Dies funktioniert, solange Sie component scanning aktiv in Ihrer Anwendung haben. Das Ergebnis wird sein, dass für jede Komponente die Feder eine Bohne erzeugt, die Sie verwenden können.

Ich schreibe dies auf einem Handy, so dass der Code nicht der beste ist.Folgen Sie einfach einem Tutorial auf @ComponentScan, oder wenn Sie brauchen, lassen Sie es mich wissen, und ich kann diese Antwort mit einem Beispiel ergänzen.

0

Schließlich ist der beste Ansatz, den ich gefunden habe, ein ConfigurationClassPostProcessor. Als Beispiel habe ich https://github.com/rinoto/spring-auto-mock

Aber da es ziemlich kompliziert und "zu viel Magie" ist, Bohnen aus dem Nichts zu erstellen, entschieden wir uns, diese Bohnen über @Bean explizit zu erstellen.

Vielen Dank für Ihre Antworten.

Verwandte Themen