web-dev-qa-db-fra.com

Comment utiliser les beans Spring Boot auto-configurés dans les fichiers de configuration XML?

J'aimerais profiter de certains des beans configurés automatiquement Spring Boot dans les fichiers de configuration XML, mais je continue de rencontrer des exceptions et des erreurs lorsque j'essaie de le faire.

Par exemple, si j'ai des bibliothèques liées aux données sur mon chemin de classe, Spring Boot configurera automatiquement un objet DataSource que je pourrai câbler automatiquement dans mes propres beans et classes, comme ceci:

@Configuration
@ImportResource("classpath:xmlconfig.xml")
public class Config {

    // This works!!
    @Autowired
    private DataSource dataSource;

    @Bean
    public ClassThatRequiresADataSource() {
        ClassThatRequiresADataSource foo = new ClassThatRequiresADataSource();
        foo.setDataSource(dataSource);
        return foo;
    }
}

Cependant, si j'essaye de faire la même chose dans un fichier de configuration XML, j'obtiendrai une exception. J'ai démarré le fichier de configuration XML en ajoutant une @ImportResource("classpath:xmlconfig.xml") à ma classe de configuration principale. Voici un exemple de ce dont je parle ... A l'intérieur xmlconfig.xml:

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

    <!-- THIS DOES NOT WORK! -->
    <bean id="anotherClassThatRequiresADataSource" class="my.package.AnotherClassThatRequiresADataSource">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>

Ce qui précède donnera une exception lors de l'exécution de l'application Spring Boot, bien que dataSource soit un nom de bean valide et configuré automatiquement. J'ai également essayé cela avec le ConnectionFactory auto-configuré (avec ActiveMQ sur le chemin de classe) et EntityManagerFactory avec Hibernate & JPA sur le chemin de classe, et rien de tout cela ne fonctionne.

Fondamentalement, ce que je demande, c'est: quel est l'équivalent du câblage automatique des beans Spring Boot auto-configurés dans un fichier de configuration XML?

Voici mon principal point d'entrée Spring Boot est juste la classe standard répertoriée dans tous les documents:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }
}

Je l'utilise principalement dans une application d'intégration Spring, où Java n'est pas encore bien prise en charge et le cœur du cadre est basé sur la configuration XML, mais j'aimerais utiliser Spring Démarrez les beans DataSource et ConnectionFactory auto-configurés dans certains des éléments d'intégration.

EDIT: La réponse fournie par @AdilF fonctionne pour le bean dataSource, mais une configuration similaire ne fonctionne pas pour le bean connectionFactory. Veuillez consulter le projet GitHub suivant pour le code de démonstration qui illustre cela:

https://github.com/ccampo133/autoconfig-test/tree/master

Si quelqu'un pouvait comprendre comment câbler correctement le bean connectionFactory, je l'apprécierais grandement.

Voici l'essentiel du code illustrant cela:

Application.Java

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Config.Java

@Configuration
@ImportResource("classpath:/resources/config.xml")
public class Config { }

FooService.Java

@Service
public class FooService {

    final private Logger logger = LoggerFactory.getLogger(FooService.class);

    @Autowired
    private DataSource dataSource;

    @Autowired
    private ConnectionFactory connectionFactory;

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @PostConstruct
    public void init() {
        Assert.notNull(dataSource, "dataSource is null!");
        logger.info("dataSource not null");

        Assert.notNull(connectionFactory, "connectionFactory is null!");
        logger.info("connectionFactory not null");

        Assert.notNull(entityManagerFactory, "entityManagerFactory is null!");
        logger.info("entityManagerFactory is not null");
    }
}

BarService.Java

public class BarService {

    final private Logger logger = LoggerFactory.getLogger(BarService.class);

    private DataSource dataSource;

    private ConnectionFactory connectionFactory;

    private EntityManagerFactory entityManagerFactory;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    public void setEntityManagerFactory(final EntityManagerFactory entityManagerFactory) {
        this.entityManagerFactory = entityManagerFactory;
    }

    @PostConstruct
    public void init() {
        Assert.notNull(dataSource, "dataSource is null!");
        logger.info("dataSource not null");

        Assert.notNull(connectionFactory, "connectionFactory is null!");
        logger.info("connectionFactory not null");

        Assert.notNull(entityManagerFactory, "entityManagerFactory is null!");
        logger.info("entityManagerFactory is not null");
    }
}

config.xml

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

    <bean id="barService" class="app.service.BarService">
        <!-- THIS WORKS! -->
        <property name="dataSource" ref="dataSource"/>

        <!-- THIS DOESN'T WORK! -->
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

</beans>

build.gradle

buildscript {
    ext {
        junitVersion = "4.11"
        springBootVersion = "1.1.5.RELEASE"
        springIntegrationVersion = "4.0.3.RELEASE"
        activeMqVersion = "5.7.0"
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
    }
}

apply plugin: "Java"
apply plugin: "Eclipse"
apply plugin: "idea"
apply plugin: "spring-boot"

configurations {
    providedRuntime
}

jar {
    baseName = "autoconfig-test"
    version = "0.0.1-SNAPSHOT"
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-milestone/" }
}

dependencies {
    // Spring Boot starters
    compile "org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}"
    compile "org.springframework.boot:spring-boot-starter-integration:${springBootVersion}"
    compile "org.springframework.integration:spring-integration-jms:${springIntegrationVersion}"

    // ActiveMQ
    compile "org.Apache.activemq:activemq-core:${activeMqVersion}"

    // Persistence
    runtime "com.h2database:h2"

    // Test
    testCompile "junit:junit:${junitVersion}"
}
18
ccampo

L'exemple de code suivant a fonctionné pour moi.

Application principale

package app;

import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.Assert;

import javax.sql.DataSource;

public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Config.class);
        DataSource dataSource = context.getBean("dataSource", DataSource.class);
        Assert.notNull(dataSource);
    }

}

Spring Java Config

package app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.*;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import javax.sql.DataSource;

@Configuration
@EnableAutoConfiguration
@EnableJpaRepositories
@ComponentScan
@ImportResource("classpath:config.xml")
public class Config {

    @Autowired
    private DataSource dataSource;

}

BarService

package app.service;

import org.springframework.util.Assert;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;

public class BarService {

    private DataSource dataSource;

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @PostConstruct
    public void init() {
        Assert.notNull(dataSource);
    }
}

FooService

package app.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

@Service
public class FooService {

    @Autowired
    DataSource dataSource;

    @PostConstruct
    public void init() {
        Assert.notNull(dataSource);
    }

}

config.xml

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

    <bean id="barService" class="app.service.BarService">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>
4
Adil F

J'ai utilisé votre exemple de projet autoconfig-test et j'ai pu le faire fonctionner. Le seul problème que j'ai trouvé avec votre xml est le suivant ...

Je suppose que vous souhaitez utiliser le courtier intégré. Lorsque j'ai exécuté votre projet, c'était ce qui était configuré automatiquement ...

@Bean
public ConnectionFactory jmsConnectionFactory() {
    return this.properties.createConnectionFactory();
}

Cela crée un bean nommé jmsConnectionFactory , cependant votre xml essaie de câbler un bean nommé connectionFactory . Changer le nom du bean en jmsConnectionFactory corrige cela ...

<bean id="barService" class="app.service.BarService">
    <property name="dataSource" ref="dataSource"/>
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

Je ne sais pas pourquoi vous voudriez utiliser xml, mais cela fonctionne.

Edit: J'ajouterai également qu'il peut y avoir un malentendu sur la façon d'utiliser l'intégration Spring JPA. Malgré le fait que le câblage automatique de l'EntityManagerFactory fonctionne, il ne devrait vraiment pas être utilisé directement. Vous devez câbler un EntityManager comme suit ...

@PersistenceContext
private EntityManager entityManager

Je sais que cela dépasse le cadre de cette question, mais je pensais simplement que je devrais ajouter que

0
hyness