我想利用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)和EntityManagerFactory
使用Hibernate&amp;类路径上的JPA,但这都不起作用。
基本上,我要问的是:什么相当于将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 Configuration尚未得到很好的支持,并且框架的核心是基于XML配置的,但是我想使用Spring在某些集成元素中引导自动配置的DataSource
和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}"
}
答案 0 :(得分:4)
以下示例代码对我有用。
主要申请
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>
答案 1 :(得分:0)
我使用了你的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
我知道它超出了这个问题的范围,但只是想我应该添加