diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBeanCreationFailureAnalyzer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBeanCreationFailureAnalyzer.java
index 3ece313e4fb3..264aa3f3154b 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBeanCreationFailureAnalyzer.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBeanCreationFailureAnalyzer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,9 +16,10 @@
 
 package org.springframework.boot.autoconfigure.r2dbc;
 
-import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.ConnectionFactoryBeanCreationException;
+import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsInitializer.ConnectionFactoryBeanCreationException;
 import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
 import org.springframework.boot.diagnostics.FailureAnalysis;
+import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
 import org.springframework.context.EnvironmentAware;
 import org.springframework.core.env.Environment;
 import org.springframework.util.ObjectUtils;
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilder.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilder.java
index 5c1ca7438de9..b57230ba530d 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilder.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,17 +17,12 @@
 package org.springframework.boot.autoconfigure.r2dbc;
 
 import java.util.function.Consumer;
-import java.util.function.Predicate;
 import java.util.function.Supplier;
 
 import io.r2dbc.spi.ConnectionFactories;
 import io.r2dbc.spi.ConnectionFactory;
 import io.r2dbc.spi.ConnectionFactoryOptions;
 import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
-import io.r2dbc.spi.Option;
-
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.util.StringUtils;
 
 /**
  * Builder for {@link ConnectionFactory}.
@@ -36,7 +31,10 @@
  * @author Tadaya Tsuyukubo
  * @author Stephane Nicoll
  * @since 2.3.0
+ * @deprecated since 2.5.0 in favor of
+ * {@link org.springframework.boot.r2dbc.ConnectionFactoryBuilder}
  */
+@Deprecated
 public final class ConnectionFactoryBuilder {
 
 	private final ConnectionFactoryOptions.Builder optionsBuilder;
@@ -59,7 +57,7 @@ private ConnectionFactoryBuilder(ConnectionFactoryOptions.Builder optionsBuilder
 	public static ConnectionFactoryBuilder of(R2dbcProperties properties,
 			Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
 		return new ConnectionFactoryBuilder(
-				new ConnectionFactoryOptionsInitializer().initializeOptions(properties, embeddedDatabaseConnection));
+				new ConnectionFactoryOptionsInitializer().initialize(properties, adapt(embeddedDatabaseConnection)));
 	}
 
 	/**
@@ -133,127 +131,13 @@ public ConnectionFactoryOptions buildOptions() {
 		return this.optionsBuilder.build();
 	}
 
-	static class ConnectionFactoryOptionsInitializer {
-
-		/**
-		 * Initialize a {@link io.r2dbc.spi.ConnectionFactoryOptions.Builder
-		 * ConnectionFactoryOptions.Builder} using the specified properties.
-		 * @param properties the properties to use to initialize the builder
-		 * @param embeddedDatabaseConnection the embedded connection to use as a fallback
-		 * @return an initialized builder
-		 * @throws ConnectionFactoryBeanCreationException if no suitable connection could
-		 * be determined
-		 */
-		ConnectionFactoryOptions.Builder initializeOptions(R2dbcProperties properties,
-				Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
-			if (StringUtils.hasText(properties.getUrl())) {
-				return initializeRegularOptions(properties);
-			}
-			EmbeddedDatabaseConnection embeddedConnection = embeddedDatabaseConnection.get();
-			if (embeddedConnection != EmbeddedDatabaseConnection.NONE) {
-				return initializeEmbeddedOptions(properties, embeddedConnection);
-			}
-			throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL",
-					properties, embeddedConnection);
-		}
-
-		private ConnectionFactoryOptions.Builder initializeRegularOptions(R2dbcProperties properties) {
-			ConnectionFactoryOptions urlOptions = ConnectionFactoryOptions.parse(properties.getUrl());
-			Builder optionsBuilder = urlOptions.mutate();
-			configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, properties::getUsername,
-					StringUtils::hasText);
-			configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, properties::getPassword,
-					StringUtils::hasText);
-			configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE,
-					() -> determineDatabaseName(properties), StringUtils::hasText);
-			if (properties.getProperties() != null) {
-				properties.getProperties().forEach((key, value) -> optionsBuilder.option(Option.valueOf(key), value));
-			}
-			return optionsBuilder;
-		}
-
-		private ConnectionFactoryOptions.Builder initializeEmbeddedOptions(R2dbcProperties properties,
-				EmbeddedDatabaseConnection embeddedDatabaseConnection) {
-			String url = embeddedDatabaseConnection.getUrl(determineEmbeddedDatabaseName(properties));
-			if (url == null) {
-				throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL",
-						properties, embeddedDatabaseConnection);
-			}
-			Builder builder = ConnectionFactoryOptions.parse(url).mutate();
-			String username = determineEmbeddedUsername(properties);
-			if (StringUtils.hasText(username)) {
-				builder.option(ConnectionFactoryOptions.USER, username);
-			}
-			if (StringUtils.hasText(properties.getPassword())) {
-				builder.option(ConnectionFactoryOptions.PASSWORD, properties.getPassword());
-			}
-			return builder;
-		}
-
-		private String determineDatabaseName(R2dbcProperties properties) {
-			if (properties.isGenerateUniqueName()) {
-				return properties.determineUniqueName();
-			}
-			if (StringUtils.hasLength(properties.getName())) {
-				return properties.getName();
-			}
-			return null;
-		}
-
-		private String determineEmbeddedDatabaseName(R2dbcProperties properties) {
-			String databaseName = determineDatabaseName(properties);
-			return (databaseName != null) ? databaseName : "testdb";
-		}
-
-		private String determineEmbeddedUsername(R2dbcProperties properties) {
-			String username = ifHasText(properties.getUsername());
-			return (username != null) ? username : "sa";
-		}
-
-		private <T extends CharSequence> void configureIf(Builder optionsBuilder,
-				ConnectionFactoryOptions originalOptions, Option<T> option, Supplier<T> valueSupplier,
-				Predicate<T> setIf) {
-			if (originalOptions.hasOption(option)) {
-				return;
-			}
-			T value = valueSupplier.get();
-			if (setIf.test(value)) {
-				optionsBuilder.option(option, value);
-			}
-		}
-
-		private ConnectionFactoryBeanCreationException connectionFactoryBeanCreationException(String message,
-				R2dbcProperties properties, EmbeddedDatabaseConnection embeddedDatabaseConnection) {
-			return new ConnectionFactoryBeanCreationException(message, properties, embeddedDatabaseConnection);
-		}
-
-		private String ifHasText(String candidate) {
-			return (StringUtils.hasText(candidate)) ? candidate : null;
-		}
-
-	}
-
-	static class ConnectionFactoryBeanCreationException extends BeanCreationException {
-
-		private final R2dbcProperties properties;
-
-		private final EmbeddedDatabaseConnection embeddedDatabaseConnection;
-
-		ConnectionFactoryBeanCreationException(String message, R2dbcProperties properties,
-				EmbeddedDatabaseConnection embeddedDatabaseConnection) {
-			super(message);
-			this.properties = properties;
-			this.embeddedDatabaseConnection = embeddedDatabaseConnection;
-		}
-
-		EmbeddedDatabaseConnection getEmbeddedDatabaseConnection() {
-			return this.embeddedDatabaseConnection;
-		}
-
-		R2dbcProperties getProperties() {
-			return this.properties;
-		}
-
+	private static Supplier<org.springframework.boot.r2dbc.EmbeddedDatabaseConnection> adapt(
+			Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
+		return () -> {
+			EmbeddedDatabaseConnection connection = embeddedDatabaseConnection.get();
+			return (connection != null)
+					? org.springframework.boot.r2dbc.EmbeddedDatabaseConnection.valueOf(connection.name()) : null;
+		};
 	}
 
 }
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryConfigurations.java
index 3f80c5f81a22..599b947c1f50 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryConfigurations.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryConfigurations.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
 import org.springframework.boot.context.properties.PropertyMapper;
+import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Condition;
 import org.springframework.context.annotation.ConditionContext;
@@ -50,7 +51,9 @@ abstract class ConnectionFactoryConfigurations {
 
 	protected static ConnectionFactory createConnectionFactory(R2dbcProperties properties, ClassLoader classLoader,
 			List<ConnectionFactoryOptionsBuilderCustomizer> optionsCustomizers) {
-		return ConnectionFactoryBuilder.of(properties, () -> EmbeddedDatabaseConnection.get(classLoader))
+		return org.springframework.boot.r2dbc.ConnectionFactoryBuilder
+				.withOptions(new ConnectionFactoryOptionsInitializer().initialize(properties,
+						() -> EmbeddedDatabaseConnection.get(classLoader)))
 				.configure((options) -> {
 					for (ConnectionFactoryOptionsBuilderCustomizer optionsCustomizer : optionsCustomizers) {
 						optionsCustomizer.customize(options);
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryOptionsInitializer.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryOptionsInitializer.java
new file mode 100644
index 000000000000..f5e10f4c7342
--- /dev/null
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryOptionsInitializer.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.autoconfigure.r2dbc;
+
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+import io.r2dbc.spi.ConnectionFactoryOptions;
+import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
+import io.r2dbc.spi.Option;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
+import org.springframework.util.StringUtils;
+
+/**
+ * Initialize a {@link ConnectionFactoryOptions.Builder} based on {@link R2dbcProperties}.
+ *
+ * @author Stephane Nicoll
+ */
+class ConnectionFactoryOptionsInitializer {
+
+	/**
+	 * Initialize a {@link io.r2dbc.spi.ConnectionFactoryOptions.Builder
+	 * ConnectionFactoryOptions.Builder} using the specified properties.
+	 * @param properties the properties to use to initialize the builder
+	 * @param embeddedDatabaseConnection the embedded connection to use as a fallback
+	 * @return an initialized builder
+	 * @throws ConnectionFactoryBeanCreationException if no suitable connection could be
+	 * determined
+	 */
+	ConnectionFactoryOptions.Builder initialize(R2dbcProperties properties,
+			Supplier<EmbeddedDatabaseConnection> embeddedDatabaseConnection) {
+		if (StringUtils.hasText(properties.getUrl())) {
+			return initializeRegularOptions(properties);
+		}
+		EmbeddedDatabaseConnection embeddedConnection = embeddedDatabaseConnection.get();
+		if (embeddedConnection != EmbeddedDatabaseConnection.NONE) {
+			return initializeEmbeddedOptions(properties, embeddedConnection);
+		}
+		throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL", properties,
+				embeddedConnection);
+	}
+
+	private ConnectionFactoryOptions.Builder initializeRegularOptions(R2dbcProperties properties) {
+		ConnectionFactoryOptions urlOptions = ConnectionFactoryOptions.parse(properties.getUrl());
+		Builder optionsBuilder = urlOptions.mutate();
+		configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.USER, properties::getUsername,
+				StringUtils::hasText);
+		configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.PASSWORD, properties::getPassword,
+				StringUtils::hasText);
+		configureIf(optionsBuilder, urlOptions, ConnectionFactoryOptions.DATABASE,
+				() -> determineDatabaseName(properties), StringUtils::hasText);
+		if (properties.getProperties() != null) {
+			properties.getProperties().forEach((key, value) -> optionsBuilder.option(Option.valueOf(key), value));
+		}
+		return optionsBuilder;
+	}
+
+	private Builder initializeEmbeddedOptions(R2dbcProperties properties,
+			EmbeddedDatabaseConnection embeddedDatabaseConnection) {
+		String url = embeddedDatabaseConnection.getUrl(determineEmbeddedDatabaseName(properties));
+		if (url == null) {
+			throw connectionFactoryBeanCreationException("Failed to determine a suitable R2DBC Connection URL",
+					properties, embeddedDatabaseConnection);
+		}
+		Builder builder = ConnectionFactoryOptions.parse(url).mutate();
+		String username = determineEmbeddedUsername(properties);
+		if (StringUtils.hasText(username)) {
+			builder.option(ConnectionFactoryOptions.USER, username);
+		}
+		if (StringUtils.hasText(properties.getPassword())) {
+			builder.option(ConnectionFactoryOptions.PASSWORD, properties.getPassword());
+		}
+		return builder;
+	}
+
+	private String determineDatabaseName(R2dbcProperties properties) {
+		if (properties.isGenerateUniqueName()) {
+			return properties.determineUniqueName();
+		}
+		if (StringUtils.hasLength(properties.getName())) {
+			return properties.getName();
+		}
+		return null;
+	}
+
+	private String determineEmbeddedDatabaseName(R2dbcProperties properties) {
+		String databaseName = determineDatabaseName(properties);
+		return (databaseName != null) ? databaseName : "testdb";
+	}
+
+	private String determineEmbeddedUsername(R2dbcProperties properties) {
+		String username = ifHasText(properties.getUsername());
+		return (username != null) ? username : "sa";
+	}
+
+	private <T extends CharSequence> void configureIf(Builder optionsBuilder, ConnectionFactoryOptions originalOptions,
+			Option<T> option, Supplier<T> valueSupplier, Predicate<T> setIf) {
+		if (originalOptions.hasOption(option)) {
+			return;
+		}
+		T value = valueSupplier.get();
+		if (setIf.test(value)) {
+			optionsBuilder.option(option, value);
+		}
+	}
+
+	private ConnectionFactoryBeanCreationException connectionFactoryBeanCreationException(String message,
+			R2dbcProperties properties, EmbeddedDatabaseConnection embeddedDatabaseConnection) {
+		return new ConnectionFactoryBeanCreationException(message, properties, embeddedDatabaseConnection);
+	}
+
+	private String ifHasText(String candidate) {
+		return (StringUtils.hasText(candidate)) ? candidate : null;
+	}
+
+	static class ConnectionFactoryBeanCreationException extends BeanCreationException {
+
+		private final R2dbcProperties properties;
+
+		private final EmbeddedDatabaseConnection embeddedDatabaseConnection;
+
+		ConnectionFactoryBeanCreationException(String message, R2dbcProperties properties,
+				EmbeddedDatabaseConnection embeddedDatabaseConnection) {
+			super(message);
+			this.properties = properties;
+			this.embeddedDatabaseConnection = embeddedDatabaseConnection;
+		}
+
+		EmbeddedDatabaseConnection getEmbeddedDatabaseConnection() {
+			return this.embeddedDatabaseConnection;
+		}
+
+		R2dbcProperties getProperties() {
+			return this.properties;
+		}
+
+	}
+
+}
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/EmbeddedDatabaseConnection.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/EmbeddedDatabaseConnection.java
index 1b4fc1e3623a..8a734e39d834 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/EmbeddedDatabaseConnection.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/r2dbc/EmbeddedDatabaseConnection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,7 +25,10 @@
  * @author Mark Paluch
  * @author Stephane Nicoll
  * @since 2.3.0
+ * @deprecated since 2.5.0 in favor of
+ * {@link org.springframework.boot.r2dbc.EmbeddedDatabaseConnection}
  */
+@Deprecated
 public enum EmbeddedDatabaseConnection {
 
 	/**
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilderTests.java
index 713e2afc8699..61af160d5950 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilderTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/ConnectionFactoryBuilderTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
 import io.r2dbc.spi.Option;
 import org.junit.jupiter.api.Test;
 
-import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.ConnectionFactoryBeanCreationException;
+import org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryOptionsInitializer.ConnectionFactoryBeanCreationException;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -33,6 +33,7 @@
  * @author Tadaya Tsuyukubo
  * @author Stephane Nicoll
  */
+@Deprecated
 class ConnectionFactoryBuilderTests {
 
 	@Test
@@ -51,7 +52,8 @@ void connectionFactoryBeanCreationProvidesConnectionAndProperties() {
 			fail("Should have thrown a " + ConnectionFactoryBeanCreationException.class.getName());
 		}
 		catch (ConnectionFactoryBeanCreationException ex) {
-			assertThat(ex.getEmbeddedDatabaseConnection()).isEqualTo(EmbeddedDatabaseConnection.NONE);
+			assertThat(ex.getEmbeddedDatabaseConnection())
+					.isEqualTo(org.springframework.boot.r2dbc.EmbeddedDatabaseConnection.NONE);
 			assertThat(ex.getProperties()).isSameAs(properties);
 		}
 	}
diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/R2dbcAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/R2dbcAutoConfigurationTests.java
index 61cafd2c8985..499c02792e07 100644
--- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/R2dbcAutoConfigurationTests.java
+++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/r2dbc/R2dbcAutoConfigurationTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2020 the original author or authors.
+ * Copyright 2012-2021 the original author or authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@
 import org.springframework.boot.autoconfigure.AutoConfigurations;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.boot.autoconfigure.r2dbc.SimpleConnectionFactoryProvider.SimpleTestConnectionFactory;
+import org.springframework.boot.r2dbc.EmbeddedDatabaseConnection;
 import org.springframework.boot.test.context.FilteredClassLoader;
 import org.springframework.boot.test.context.runner.ApplicationContextRunner;
 import org.springframework.context.annotation.Bean;
diff --git a/spring-boot-project/spring-boot/build.gradle b/spring-boot-project/spring-boot/build.gradle
index 9a644b6823d4..a55b7353b397 100644
--- a/spring-boot-project/spring-boot/build.gradle
+++ b/spring-boot-project/spring-boot/build.gradle
@@ -61,6 +61,7 @@ dependencies {
 	optional("org.springframework:spring-messaging")
 	optional("org.springframework:spring-orm")
 	optional("org.springframework:spring-oxm")
+    optional("org.springframework:spring-r2dbc")
 	optional("org.springframework:spring-test")
 	optional("org.springframework:spring-web")
 	optional("org.springframework:spring-webflux")
@@ -81,6 +82,7 @@ dependencies {
 	testImplementation("com.squareup.okhttp3:okhttp")
 	testImplementation("com.sun.xml.messaging.saaj:saaj-impl")
 	testImplementation("io.projectreactor:reactor-test")
+    testImplementation("io.r2dbc:r2dbc-h2")
 	testImplementation("javax.xml.ws:jaxws-api")
 	testImplementation("mysql:mysql-connector-java")
 	testImplementation("net.sourceforge.jtds:jtds")
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilder.java
new file mode 100644
index 000000000000..40e66a7af17a
--- /dev/null
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilder.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.r2dbc;
+
+import java.util.function.Consumer;
+
+import io.r2dbc.spi.ConnectionFactories;
+import io.r2dbc.spi.ConnectionFactory;
+import io.r2dbc.spi.ConnectionFactoryOptions;
+import io.r2dbc.spi.ConnectionFactoryOptions.Builder;
+
+import org.springframework.util.Assert;
+
+/**
+ * Builder for {@link ConnectionFactory}.
+ *
+ * @author Mark Paluch
+ * @author Tadaya Tsuyukubo
+ * @author Stephane Nicoll
+ * @since 2.5.0
+ */
+public final class ConnectionFactoryBuilder {
+
+	private final Builder optionsBuilder;
+
+	private ConnectionFactoryBuilder(Builder optionsBuilder) {
+		this.optionsBuilder = optionsBuilder;
+	}
+
+	/**
+	 * Initialize a new {@link ConnectionFactoryBuilder} based on the specified R2DBC url.
+	 * @param url the url to use
+	 * @return a new builder initialized with the options exposed in the specified url
+	 * @see EmbeddedDatabaseConnection#getUrl(String)
+	 */
+	public static ConnectionFactoryBuilder withUrl(String url) {
+		Assert.hasText(url, () -> "Url must not be null");
+		return withOptions(ConnectionFactoryOptions.parse(url).mutate());
+	}
+
+	/**
+	 * Initialize a new {@link ConnectionFactoryBuilder} based on the specified
+	 * {@link Builder options}.
+	 * @param options the options to use to initialize the builder
+	 * @return a new builder initialized with the settings defined in the given
+	 * {@link Builder options}
+	 */
+	public static ConnectionFactoryBuilder withOptions(Builder options) {
+		return new ConnectionFactoryBuilder(options);
+	}
+
+	/**
+	 * Configure additional options.
+	 * @param options a {@link Consumer} to customize the options
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder configure(Consumer<Builder> options) {
+		options.accept(this.optionsBuilder);
+		return this;
+	}
+
+	/**
+	 * Configure the {@linkplain ConnectionFactoryOptions#USER username}.
+	 * @param username the connection factory username
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder username(String username) {
+		return configure((options) -> options.option(ConnectionFactoryOptions.USER, username));
+	}
+
+	/**
+	 * Configure the {@linkplain ConnectionFactoryOptions#PASSWORD password}.
+	 * @param password the connection factory password
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder password(CharSequence password) {
+		return configure((options) -> options.option(ConnectionFactoryOptions.PASSWORD, password));
+	}
+
+	/**
+	 * Configure the {@linkplain ConnectionFactoryOptions#HOST host name}.
+	 * @param host the connection factory hostname
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder hostname(String host) {
+		return configure((options) -> options.option(ConnectionFactoryOptions.HOST, host));
+	}
+
+	/**
+	 * Configure the {@linkplain ConnectionFactoryOptions#PORT port}.
+	 * @param port the connection factory port
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder port(int port) {
+		return configure((options) -> options.option(ConnectionFactoryOptions.PORT, port));
+	}
+
+	/**
+	 * Configure the {@linkplain ConnectionFactoryOptions#DATABASE database}.
+	 * @param database the connection factory database
+	 * @return this for method chaining
+	 */
+	public ConnectionFactoryBuilder database(String database) {
+		return configure((options) -> options.option(ConnectionFactoryOptions.DATABASE, database));
+	}
+
+	/**
+	 * Build a {@link ConnectionFactory} based on the state of this builder.
+	 * @return a connection factory
+	 */
+	public ConnectionFactory build() {
+		return ConnectionFactories.get(buildOptions());
+	}
+
+	/**
+	 * Build a {@link ConnectionFactoryOptions} based on the state of this builder.
+	 * @return the options
+	 */
+	public ConnectionFactoryOptions buildOptions() {
+		return this.optionsBuilder.build();
+	}
+
+}
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnection.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnection.java
new file mode 100644
index 000000000000..18b664d2a6cc
--- /dev/null
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnection.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.r2dbc;
+
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+
+/**
+ * Connection details for embedded databases compatible with r2dbc.
+ *
+ * @author Mark Paluch
+ * @author Stephane Nicoll
+ * @since 2.5.0
+ */
+public enum EmbeddedDatabaseConnection {
+
+	/**
+	 * No Connection.
+	 */
+	NONE(null, null),
+
+	/**
+	 * H2 Database Connection.
+	 */
+	H2("io.r2dbc.h2.H2ConnectionFactoryProvider",
+			"r2dbc:h2:mem:///%s?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+
+	private final String driverClassName;
+
+	private final String url;
+
+	EmbeddedDatabaseConnection(String driverClassName, String url) {
+		this.driverClassName = driverClassName;
+		this.url = url;
+	}
+
+	/**
+	 * Returns the driver class name.
+	 * @return the driver class name
+	 */
+	public String getDriverClassName() {
+		return this.driverClassName;
+	}
+
+	/**
+	 * Returns the R2DBC URL for the connection using the specified {@code databaseName}.
+	 * @param databaseName the name of the database
+	 * @return the connection URL
+	 */
+	public String getUrl(String databaseName) {
+		Assert.hasText(databaseName, "DatabaseName must not be empty");
+		return (this.url != null) ? String.format(this.url, databaseName) : null;
+	}
+
+	/**
+	 * Returns the most suitable {@link EmbeddedDatabaseConnection} for the given class
+	 * loader.
+	 * @param classLoader the class loader used to check for classes
+	 * @return an {@link EmbeddedDatabaseConnection} or {@link #NONE}.
+	 */
+	public static EmbeddedDatabaseConnection get(ClassLoader classLoader) {
+		for (EmbeddedDatabaseConnection candidate : EmbeddedDatabaseConnection.values()) {
+			if (candidate != NONE && ClassUtils.isPresent(candidate.getDriverClassName(), classLoader)) {
+				return candidate;
+			}
+		}
+		return NONE;
+	}
+
+}
diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/package-info.java
new file mode 100644
index 000000000000..6344ee642da6
--- /dev/null
+++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/r2dbc/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Support for R2DBC connectivity.
+ */
+package org.springframework.boot.r2dbc;
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilderTests.java
new file mode 100644
index 000000000000..2724f1a8b0d0
--- /dev/null
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/ConnectionFactoryBuilderTests.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.r2dbc;
+
+import java.util.UUID;
+
+import io.r2dbc.h2.H2ConnectionFactoryMetadata;
+import io.r2dbc.spi.ConnectionFactory;
+import io.r2dbc.spi.ConnectionFactoryOptions;
+import io.r2dbc.spi.Option;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+
+/**
+ * Tests for {@link ConnectionFactoryBuilder}.
+ *
+ * @author Mark Paluch
+ * @author Tadaya Tsuyukubo
+ * @author Stephane Nicoll
+ */
+class ConnectionFactoryBuilderTests {
+
+	@Test
+	void createWithNullUrlShouldFail() {
+		assertThatIllegalArgumentException().isThrownBy(() -> ConnectionFactoryBuilder.withUrl(null));
+	}
+
+	@Test
+	void createWithEmptyUrlShouldFail() {
+		assertThatIllegalArgumentException().isThrownBy(() -> ConnectionFactoryBuilder.withUrl("  "));
+	}
+
+	@Test
+	void createWithEmbeddedConnectionNoneShouldFail() {
+		assertThatIllegalArgumentException()
+				.isThrownBy(() -> ConnectionFactoryBuilder.withUrl(EmbeddedDatabaseConnection.NONE.getUrl("test")));
+	}
+
+	@Test
+	void buildOptionsWithBasicUrlShouldExposeOptions() {
+		ConnectionFactoryOptions options = ConnectionFactoryBuilder.withUrl("r2dbc:simple://:pool:").buildOptions();
+		assertThat(options.hasOption(ConnectionFactoryOptions.USER)).isFalse();
+		assertThat(options.hasOption(ConnectionFactoryOptions.PASSWORD)).isFalse();
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("simple");
+	}
+
+	@Test
+	void buildOptionsWithEmbeddedConnectionH2ShouldExposeOptions() {
+		ConnectionFactoryOptions options = ConnectionFactoryBuilder
+				.withUrl(EmbeddedDatabaseConnection.H2.getUrl("testdb")).buildOptions();
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("h2");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PROTOCOL)).isEqualTo("mem");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("testdb");
+		assertThat(options.hasOption(ConnectionFactoryOptions.HOST)).isFalse();
+		assertThat(options.hasOption(ConnectionFactoryOptions.PORT)).isFalse();
+		assertThat(options.hasOption(ConnectionFactoryOptions.USER)).isFalse();
+		assertThat(options.hasOption(ConnectionFactoryOptions.PASSWORD)).isFalse();
+		assertThat(options.getValue(Option.<String>valueOf("options")))
+				.isEqualTo("DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
+	}
+
+	@Test
+	void buildOptionsWithCompleteUrlShouldExposeOptions() {
+		ConnectionFactoryOptions options = ConnectionFactoryBuilder
+				.withUrl("r2dbc:simple:proto://user:password@myhost:4711/mydatabase").buildOptions();
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DRIVER)).isEqualTo("simple");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PROTOCOL)).isEqualTo("proto");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.USER)).isEqualTo("user");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("password");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.HOST)).isEqualTo("myhost");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PORT)).isEqualTo(4711);
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("mydatabase");
+	}
+
+	@Test
+	void buildOptionsWithSpecificSettingsShouldOverrideUrlOptions() {
+		ConnectionFactoryOptions options = ConnectionFactoryBuilder
+				.withUrl("r2dbc:simple://user:password@myhost/mydatabase").username("another-user")
+				.password("another-password").hostname("another-host").port(1234).database("another-database")
+				.buildOptions();
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.USER)).isEqualTo("another-user");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("another-password");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.HOST)).isEqualTo("another-host");
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.PORT)).isEqualTo(1234);
+		assertThat(options.getRequiredValue(ConnectionFactoryOptions.DATABASE)).isEqualTo("another-database");
+	}
+
+	@Test
+	void buildOptionsWithDriverPropertiesShouldExposeOptions() {
+		ConnectionFactoryOptions options = ConnectionFactoryBuilder.withUrl("r2dbc:simple://user:password@myhost")
+				.configure(
+						(o) -> o.option(Option.valueOf("simpleOne"), "one").option(Option.valueOf("simpleTwo"), "two"))
+				.buildOptions();
+		assertThat(options.getRequiredValue(Option.<String>valueOf("simpleOne"))).isEqualTo("one");
+		assertThat(options.getRequiredValue(Option.<String>valueOf("simpleTwo"))).isEqualTo("two");
+	}
+
+	@Test
+	void buildShouldExposeConnectionFactory() {
+		String databaseName = UUID.randomUUID().toString();
+		ConnectionFactory connectionFactory = ConnectionFactoryBuilder
+				.withUrl(EmbeddedDatabaseConnection.H2.getUrl(databaseName)).build();
+		assertThat(connectionFactory).isNotNull();
+		assertThat(connectionFactory.getMetadata().getName()).isEqualTo(H2ConnectionFactoryMetadata.NAME);
+	}
+
+}
diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnectionTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnectionTests.java
new file mode 100644
index 000000000000..a6ca5d2f93cd
--- /dev/null
+++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/r2dbc/EmbeddedDatabaseConnectionTests.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.r2dbc;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link EmbeddedDatabaseConnection}.
+ *
+ * @author Stephane Nicoll
+ */
+class EmbeddedDatabaseConnectionTests {
+
+	@ParameterizedTest
+	@MethodSource("urlParameters")
+	void getUrlWithTestDatabase(EmbeddedDatabaseConnection connection, String expectUrl) {
+		assertThat(connection.getUrl("test-database")).isEqualTo(expectUrl);
+	}
+
+	@Test
+	void getReturnsH2ByDefault() {
+		assertThat(EmbeddedDatabaseConnection.get(EmbeddedDatabaseConnectionTests.class.getClassLoader()))
+				.isEqualTo(EmbeddedDatabaseConnection.H2);
+	}
+
+	@Test
+	void getWhenH2IsNotOnTheClasspathReturnsNone() {
+		assertThat(EmbeddedDatabaseConnection.get(new HidePackagesClassLoader("io.r2dbc.h2")))
+				.isEqualTo(EmbeddedDatabaseConnection.NONE);
+	}
+
+	static Stream<Arguments> urlParameters() {
+		return Stream.of(Arguments.arguments(EmbeddedDatabaseConnection.NONE, null),
+				Arguments.arguments(EmbeddedDatabaseConnection.H2,
+						"r2dbc:h2:mem:///test-database?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"));
+	}
+
+	private static class HidePackagesClassLoader extends URLClassLoader {
+
+		private final String[] hiddenPackages;
+
+		HidePackagesClassLoader(String... hiddenPackages) {
+			super(new URL[0], EmbeddedDatabaseConnectionTests.HidePackagesClassLoader.class.getClassLoader());
+			this.hiddenPackages = hiddenPackages;
+		}
+
+		@Override
+		protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+			if (Arrays.stream(this.hiddenPackages).anyMatch(name::startsWith)) {
+				throw new ClassNotFoundException();
+			}
+			return super.loadClass(name, resolve);
+		}
+
+	}
+
+}