SpringFramework XML-Config und Annotations mixen

Wer “Spring” hört, denkt meistens sofort an riesige XML-Konfigurationen, und der ein oder andere verspürt das Bedürfnis, direkt über Spring herziehen zu müssen. Tatsächlich kann man aber inzwischen so ziemlich alles auch per Annotations konfigurieren.
Hin und wieder kommt man aber nicht umher, beides zu mischen – z.B. wenn es darum geht ein altes Projekt nach und nach zu refactoren und nicht alles auf einmal vom Kopf auf die Füße gestellt werden soll oder kann.

Dabei das wichtigste direkt vorweg. Wenn es nur darum geht per context:component-scan  und context:annotation-config  bestehende Beans zu erzeugen und zu injecten, dann ist das ohne weiteres möglich. Im Prinzip sind nur 4 Zeilen Code:

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); 
Resource contextResource = new ClassPathResource("context/context-core.xml"); 
xmlBeanDefinitionReader.loadBeanDefinitions(contextResource);

Das XML muss dabei im günstigen Fall nicht komplexer aussehen als:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config/>

    <context:component-scan base-package="de.flaviait.testfw" />
</beans>

Spannender wird es aber, wenn noch Klassen existieren, die ihrerseits als BeanFactory fungieren bzw. per Annotation als solche definiert wurden. Bspw.:

@Configuration
public class ExampleBeanProvider {
    @Bean
    public ExampleBean exampleBean() {
        new ExampleBean();
    }
}

Die Zuvor geschilderte Konfiguration würde zwar eine Bean für ExampleBeanProvider erzeugen, nicht aber für ExampleBean.
Um das zu lösen, müssen wir den Annotations dediziert zu Leibe rücken. Zum Beispiel mit einem AnnotationConfigApplicationContext:

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext("de.flaviait");

Wird der Classpath im Constructor angegeben, wird direkt ein Scan durchgeführt. Alternativ könnte man das auch später tun:

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.scan("de.flaviait");
annotationConfigApplicationContext.refresh();

Da wir natürlich für die Beans aus der XML-Konfiguration die selbe BeanFactory benutzen möchten, müssen wir zum Parsen etwas anders vorgehen, indem wir keine neue DefaultListableBeanFactory erzeugen, sondern die aus dem Context benutzen:

DefaultListableBeanFactory beanFactory = annotationConfigApplicationContext.getDefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
Resource contextResource = new ClassPathResource("context/context-core.xml");
xmlBeanDefinitionReader.loadBeanDefinitions(contextResource);

Zu beachten wäre dabei nur noch, dass der AnnotationConfigApplicationContext natürlich zuerst zum Zug kommt. Das ist wichtig, weil es zu Problemen führen kann. Zum Beispiel wenn man spring-aop benutzen möchte und den Aspect per Annotation konfiguriert aber die aop-config in der XML definiert. Aber dazu mehr in einem anderen Blogeintrag über gewisse Eigenarten von spring-aop und mögliche Fallstricke.

Teilen Sie diesen Beitrag

Das könnte dich auch interessieren …

Eine Antwort

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Durch die weitere Nutzung der Seite stimmen Sie der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen