如何在 XML 配置文件中使用 Spring Boot 自动配置的 bean?
Posted
技术标签:
【中文标题】如何在 XML 配置文件中使用 Spring Boot 自动配置的 bean?【英文标题】:How can I use Spring Boot auto-configured beans in XML configuration files? 【发布时间】:2014-10-19 04:15:16 【问题描述】:我想利用 XML 配置文件中的一些 Spring Boot 自动配置的 bean,但是当我尝试这样做时,我总是遇到异常和错误。
例如,如果我的类路径上有与数据相关的库,Spring Boot 将自动配置一个 DataSource
对象,我可以将其自动装配到我自己的 bean 和类中,如下所示:
@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;
但是,如果我尝试在 XML 配置文件中做同样的事情,我会得到一个异常。我一直在通过将@ImportResource("classpath:xmlconfig.xml")
添加到我的主配置类来引导 XML 配置文件。这是我正在谈论的一个例子......内部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>
尽管dataSource
是一个有效的、自动配置的 Bean 名称,但在运行 Spring Boot 应用程序时,上述内容会出现异常。我还尝试使用自动配置的ConnectionFactory
(在类路径上使用 ActiveMQ)和在类路径上使用 Hibernate 和 JPA 的EntityManagerFactory
,但这些都不起作用。
基本上,我要问的是:什么相当于将 Spring Boot 自动配置的 bean 自动装配到 XML 配置文件中?
这是我的主要 Spring Boot 入口点,只是所有文档中列出的标准类:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application
public static void main(String[] args) throws Exception
SpringApplication.run(Application.class, args);
我主要在 Spring Integration 应用程序中使用它,其中 Java 配置尚未得到很好的支持,框架的核心是基于 XML 配置的,但我想使用 Spring Boot 自动配置 @987654331 @ 和ConnectionFactory
bean 中的一些集成元素。
编辑:@AdilF 提供的答案适用于 dataSource
bean,但类似的配置不适用于 connectionFactory
bean。请参阅以下 GitHub 项目的演示代码来说明这一点:
https://github.com/ccampo133/autoconfig-test/tree/master
如果有人能弄清楚如何正确连接connectionFactory
bean,我将不胜感激。
以下是说明这一点的大部分代码:
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"
【问题讨论】:
您在哪里创建数据源?您的 java 配置和 xml 配置都没有创建数据源。 Spring Boot 如果你启用了@EnableAutoConfiguration
功能,就会自动创建一个DataSource
。然后,您可以将其自动连接到您的 JavaConfig bean。
对于初学者,您的Application
类需要在已经存在的内容旁边添加@Configuration
注释。基于 Java 的配置和 XML 配置之间的主要区别在于,Java 配置基于类型注入,而 XML 配置基于名称。我建议不要创建 Config
类,而是将那里的 @Configuration
和 @ImportResource
移动到您的应用程序类(或者将 Application
类上的内容移动到您的 Config
类)。跨度>
应用程序类用@Configuration
注解。我一定在帖子里把它漏掉了。无论哪种情况,如果我将所有内容都移至应用程序类,我仍然会遇到同样的问题。 @ComponentScan
注释的目的是让我不必在主类中包含所有 bean 定义,因此它不应该改变任何东西。
您需要做的就是从您的Application.java
文件中删除@Configuration @ComponentScan @EnableAutoConfiguration
并将其放在Config.java
上。这对我有用。
【参考方案1】:
以下示例代码对我有用。
主要应用
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 配置
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;
酒吧服务
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>
【讨论】:
我启动 Spring Boot 的主类已经设置了该注释......所以那里没有骰子。我应该在我的原始帖子中更清楚 - 我会继续更新它。 在这种情况下,将--debug
选项添加到命令行参数并检查 spring boot 是否正在获取所有配置。如果你可以发布一个描述问题的 github 项目,我可以看看。
当使用--debug
运行时,Boot 甚至没有足够远来吐出自动配置报告。它似乎是先解析 XML 文件,然后再做其他任何事情。
你的类路径上有spring-boot-starter-data-jpa
吗?
是的。你有一个简单的项目吗?我想看看。【参考方案2】:
我使用了您的 autoconfig-test 示例项目并且能够让它工作。我发现您的 xml 的唯一问题如下...
我假设您想使用嵌入式代理。当我运行你的项目时,这是自动配置的......
@Bean
public ConnectionFactory jmsConnectionFactory()
return this.properties.createConnectionFactory();
这将创建一个名为 jmsConnectionFactory 的 bean,但是您的 xml 正在尝试连接一个名为 connectionFactory 的 bean。将 bean 名称更改为 jmsConnectionFactory 修复了该问题...
<bean id="barService" class="app.service.BarService">
<property name="dataSource" ref="dataSource"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
我不知道你为什么要使用 xml,但它确实有效。
编辑: 我还要补充一下,对于如何使用spring jpa集成可能存在一些误解。尽管 EntityManagerFactory 的自动装配确实有效,但它确实不应该直接使用。您应该按如下方式连接 EntityManager...
@PersistenceContext
private EntityManager entityManager
我知道它超出了这个问题的范围,但我只是想我应该补充一下
【讨论】:
以上是关于如何在 XML 配置文件中使用 Spring Boot 自动配置的 bean?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 xml 配置文件、JAVA、Spring 安全性对 LDAP 用户进行身份验证