[英]Spring Boot auto-configuration order
I want to create a Spring Boot auto-configuration class that (conditionally) creates a single bean A
. 我想创建一个Spring Boot自动配置类,它(有条件地)创建一个bean
A
The challenge however is, that this been has to be created before another bean B
is created in one of Spring Boot's default auto-configuration classes. 然而,挑战是必须在Spring Boot的默认自动配置类之一中创建另一个bean
B
之前创建。 The bean B
does not depend on A
. 豆
B
不依赖于A
My first try was to use @AutoConfigureBefore
. 我的第一次尝试是使用
@AutoConfigureBefore
。 That didn't work the way I expected and judging from this comment by Dave Syer it shouldn't. 这不符合我的预期,并且从Dave Syer的评论中判断它不应该。
Some background: The aforementioned bean A
alters a Mongo Database and this has to happen before MongoTemplate
is created. 一些背景:前面提到的bean
A
改变了Mongo数据库,这必须在创建MongoTemplate
之前发生。
It turns out, what I want is to dynamically make instances of B
depend on A
. 事实证明,我想要的是动态地使
B
实例依赖于A
This can be achieved by using a BeanFactoryPostProcessor
to alter the bean definitions of B
beans. 这可以通过使用
BeanFactoryPostProcessor
来改变 B
豆的bean定义来实现。
public class DependsOnPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
beanFactory, B.class, true, false);
for (String beanName : beanNames) {
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
definition.setDependsOn(StringUtils.addStringToArray(
definition.getDependsOn(), "beanNameOfB");
}
}
}
This works with plain Spring, no Spring Boot required. 这适用于普通的Spring,不需要Spring Boot。 To complete the auto-configuration I need to add the bean definition for the
DependsOnPostProcessor
to the configuration class that instantiates the bean A
. 要完成自动配置,我需要将
DependsOnPostProcessor
的bean定义添加到实例化bean A
的配置类中。
There is a new annotation @AutoConfigureOrder in Boot 1.3.0. Boot 1.3.0中有一个新的注释@AutoConfigureOrder。 Though it is unclear to me at least if this would still behave the same way as @AutoConfiugreBefore.
虽然我至少不清楚这是否仍然与@AutoConfiugreBefore相同。
Refer to @hzpz 's answer, here is a example for create database before the auto-configuration of Hikari data source. 请参阅@hzpz的答案,这是在Hikari数据源自动配置之前创建数据库的示例。
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
@Configuration
public class CreateDatabaseConfig {
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.hikari.username}")
private String username;
@Value("${spring.datasource.hikari.password}")
private String password;
@Value("${spring.datasource.hikari.catalog}")
private String catalog;
@Bean
public static BeanFactoryPostProcessor dependsOnPostProcessor() {
return beanFactory -> {
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
beanFactory, HikariDataSource.class, true, false);
for (String beanName : beanNames) {
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
definition.setDependsOn(StringUtils.addStringToArray(
definition.getDependsOn(), "createDatabaseConfig"));
}
};
}
@PostConstruct
public void init() {
try (
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement()
) {
statement.executeUpdate(
"CREATE DATABASE IF NOT EXISTS `" + catalog
+ "` DEFAULT CHARACTER SET = utf8mb4 COLLATE utf8mb4_unicode_ci;"
);
} catch (SQLException e) {
throw new RuntimeException("Create Database Fail", e);
}
}
}
More initialization for schema and data can be done with data.sql
and schema.sql
, see 85. Database Initialization 为架构和数据初始化更可以用做
data.sql
和schema.sql
,看看85.数据库初始化
ps. PS。 I tried to
CREATE DATABASE
in schema.sql
but failed, and the example above works :) 我尝试在
schema.sql
CREATE DATABASE
但失败了,上面的例子工作:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.