清淨
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • Java

    • Java 基础
  • 框架

    • Flyway
    • MapStruct
    • Spring Cloud
  • 中间件

    • Elasticsearch
    • Redis
    • RabbitMQ
    • Kafka
  • 三剑客

    • HTML
    • CSS
    • JavaScript
  • 进阶

    • jQuery
    • ECMAScript6
    • TypeScript
  • Vue

    • Vue2
    • Vue3
    • VuePress
  • Linux
  • Jenkins
  • Maven
  • MySQL
  • 插件工具
  • 代码集成
  • 其它

    • 数据结构与算法
    • 计算机网络
    • 操作系统
    • 设计模式
迁移日志
订阅号
微信订阅号
微信订阅号
GitHub
  • Flyway

    • 简介
    • 快速开始
    • Spring Boot 整合原理
    • Flyway 原理
    • 配置

Spring Boot 整合原理

在 快速开始 中,我们已经介绍了 Flyway 的基本使用方法。现在我们来深入了解 Flyway 的工作原理。

在 Spring Boot 中,Flyway 的集成是通过 FlywayAutoConfiguration 类实现的,如果我们项目中引入了 Flyway 的依赖,那么这个自动配置类就会生效。

  • FlywayAutoConfiguration.java
@Configuration(proxyBeanMethods = false)
// 有 flyway 的依赖时,自动配置才生效
@ConditionalOnClass(Flyway.class)
@Conditional(FlywayDataSourceCondition.class)
// 如果配置了 spring.flyway.enabled=true,才启用 Flyway;没配置的话,默认启用
@ConditionalOnProperty(prefix = "spring.flyway", name = "enabled", matchIfMissing = true)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class })
@Import(DatabaseInitializationDependencyConfigurer.class)
public class FlywayAutoConfiguration {

	@Bean
	@ConfigurationPropertiesBinding
	public StringOrNumberToMigrationVersionConverter stringOrNumberMigrationVersionConverter() {
		return new StringOrNumberToMigrationVersionConverter();
	}

	@Bean
	public FlywaySchemaManagementProvider flywayDefaultDdlModeProvider(ObjectProvider<Flyway> flyways) {
		return new FlywaySchemaManagementProvider(flyways);
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(JdbcUtils.class)
	@ConditionalOnMissingBean(Flyway.class)
	@EnableConfigurationProperties(FlywayProperties.class)
	public static class FlywayConfiguration {

		/**
		 * 根据配置,往容器中放入 Flyway 的 bean
		 */
		@Bean
		public Flyway flyway(FlywayProperties properties, ResourceLoader resourceLoader,
				ObjectProvider<DataSource> dataSource, @FlywayDataSource ObjectProvider<DataSource> flywayDataSource,
				ObjectProvider<FlywayConfigurationCustomizer> fluentConfigurationCustomizers,
				ObjectProvider<JavaMigration> javaMigrations, ObjectProvider<Callback> callbacks) {
			FluentConfiguration configuration = new FluentConfiguration(resourceLoader.getClassLoader());
			configureDataSource(configuration, properties, flywayDataSource.getIfAvailable(), dataSource.getIfUnique());
			checkLocationExists(configuration.getDataSource(), properties, resourceLoader);
			configureProperties(configuration, properties);
			List<Callback> orderedCallbacks = callbacks.orderedStream().collect(Collectors.toList());
			configureCallbacks(configuration, orderedCallbacks);
			fluentConfigurationCustomizers.orderedStream().forEach((customizer) -> customizer.customize(configuration));
			configureFlywayCallbacks(configuration, orderedCallbacks);
			List<JavaMigration> migrations = javaMigrations.stream().collect(Collectors.toList());
			configureJavaMigrations(configuration, migrations);
			return configuration.load();
		}

		/**
		 * 放入 FlywayMigrationInitializer 的 bean
		 */
		@Bean
		@ConditionalOnMissingBean
		public FlywayMigrationInitializer flywayInitializer(Flyway flyway,
				ObjectProvider<FlywayMigrationStrategy> migrationStrategy) {
			return new FlywayMigrationInitializer(flyway, migrationStrategy.getIfAvailable());
		}
	}

    // 省略其他代码
}
  • FlywayMigrationInitializer.java
public class FlywayMigrationInitializer implements InitializingBean, Ordered {

	private final Flyway flyway;

	private final FlywayMigrationStrategy migrationStrategy;

	private int order = 0;

	/**
	 * Create a new {@link FlywayMigrationInitializer} instance.
	 * @param flyway the flyway instance
	 */
	public FlywayMigrationInitializer(Flyway flyway) {
		this(flyway, null);
	}

	/**
	 * Create a new {@link FlywayMigrationInitializer} instance.
	 * @param flyway the flyway instance
	 * @param migrationStrategy the migration strategy or {@code null}
	 */
	public FlywayMigrationInitializer(Flyway flyway, FlywayMigrationStrategy migrationStrategy) {
		Assert.notNull(flyway, "Flyway must not be null");
		this.flyway = flyway;
		this.migrationStrategy = migrationStrategy;
	}

	/**
	 * 执行 Flyway 的迁移操作
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		if (this.migrationStrategy != null) {
			this.migrationStrategy.migrate(this.flyway);
		}
		else {
			try {
				this.flyway.migrate();
			}
			catch (NoSuchMethodError ex) {
				// Flyway < 7.0
				this.flyway.getClass().getMethod("migrate").invoke(this.flyway);
			}
		}
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

}

其实很简单,在 FlywayAutoConfiguration 中,首先会根据配置往 IOC 容器中放入一个 Flyway、FlywayMigrationInitializer 的 bean。然后在 FlywayMigrationInitializer 的 afterPropertiesSet 方法中,会调用 flyway.migrate() 方法来执行数据库迁移。

接下来,我们研究一下 Flyway#migrate() 方法的实现,见 Flyway 原理。

想要编辑此页?
上次更新: 2026/8/27 23:22
贡献者: Junfeng Dai
←快速开始Flyway 原理→
[ 纸上得来终觉浅绝知此事要躬行 ]
Copyright © 2021-present Junfeng Dai
蜀ICP备2021009537号