我想创建一个Spring Boot自动配置类,它(有条件地)创建一个bean A
。但挑战是,必须在Spring Boot的默认自动配置类之一中创建另一个bean B
之前创建它。 bean B
不依赖于A
。
我的第一次尝试是使用@AutoConfigureBefore
。这不符合我的预期,并且由Dave Syer从this comment判断它不应该。
一些背景知识:前面提到的bean A
改变了Mongo数据库,这必须在MongoTemplate
创建之前发生。
答案 0 :(得分:3)
事实证明,我想要的是动态地使B
的实例依赖于A
。这可以通过使用BeanFactoryPostProcessor
到alter the bean definitions 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");
}
}
}
这适用于普通的Spring,不需要Spring Boot。要完成自动配置,我需要将DependsOnPostProcessor
的bean定义添加到实例化bean A
的配置类中。
答案 1 :(得分:0)
Boot 1.3.0中有一个新的注释@AutoConfigureOrder。虽然至少我不清楚这是否仍然与@AutoConfiugreBefore相同。
答案 2 :(得分:0)
请参阅@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);
}
}
}
可以使用data.sql
和schema.sql
完成模式和数据的更多初始化,请参见85. Database Initialization
ps。我尝试在CREATE DATABASE
中使用schema.sql
,但失败了,上面的示例有效:)