Polish 'Allow ConnectionDetailsFactories to use context class loader'
Refine the submitted pull-request to remove the configuration property with the assumption that the context classloader will work for all cases. See gh-45014
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Pedro Xavier Leite Cavadas
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public class ConnectionDetailsFactories {
|
||||
@@ -48,25 +49,22 @@ public class ConnectionDetailsFactories {
|
||||
private final List<Registration<?, ?>> registrations = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Create a new {@link ConnectionDetailsFactories} instance. This constructor uses the
|
||||
* class loader of {@link ConnectionDetailsFactory} class to load the factories.
|
||||
* Create a new {@link ConnectionDetailsFactories} instance.
|
||||
* @deprecated since 3.5.0 for removal in 4.0.0 in favor of
|
||||
* {@link #ConnectionDetailsFactories(ClassLoader)}
|
||||
*/
|
||||
@Deprecated(since = "3.5.0", forRemoval = true)
|
||||
public ConnectionDetailsFactories() {
|
||||
this(false);
|
||||
this((ClassLoader) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConnectionDetailsFactories} instance. This constructor takes a
|
||||
* boolean argument to determine whether the context class loader should be used to
|
||||
* load the factories. If {@code true} and the context class loader is available it
|
||||
* will be used otherwise the class loader of {@link ConnectionDetailsFactory} class
|
||||
* will be used.
|
||||
* @param useContextClassLoader if {@code true} and the context class loader is
|
||||
* available it will be used otherwise the class loader of
|
||||
* {@link ConnectionDetailsFactory} class will be used.
|
||||
* Create a new {@link ConnectionDetailsFactories} instance.
|
||||
* @param classLoader the class loader used to load factories
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public ConnectionDetailsFactories(boolean useContextClassLoader) {
|
||||
this(SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader(useContextClassLoader)));
|
||||
public ConnectionDetailsFactories(ClassLoader classLoader) {
|
||||
this(SpringFactoriesLoader.forDefaultResourceLocation(classLoader));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@@ -125,24 +123,6 @@ public class ConnectionDetailsFactories {
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link ClassLoader} to use for loading factories.
|
||||
* <p>
|
||||
* The default implementation returns the context class loader of the current thread
|
||||
* or the class loader of this class if the context class loader is {@code null}.
|
||||
* @param useContextClassLoader if {@code true} and the context class loader is
|
||||
* available it will be used otherwise the class loader of
|
||||
* {@link ConnectionDetailsFactory} class will be used
|
||||
* @return the class loader to use for loading factories
|
||||
*/
|
||||
private static ClassLoader getClassLoader(boolean useContextClassLoader) {
|
||||
if (!useContextClassLoader) {
|
||||
return ConnectionDetailsFactory.class.getClassLoader();
|
||||
}
|
||||
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
return (classLoader != null) ? classLoader : getClassLoader(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ConnectionDetailsFactory} registration.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -46,11 +46,6 @@ public class DockerComposeProperties {
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Whether to try to use the context class loader for connection details factories.
|
||||
*/
|
||||
private boolean useContextClassLoader = false;
|
||||
|
||||
/**
|
||||
* Arguments to pass to the Docker Compose command.
|
||||
*/
|
||||
@@ -94,18 +89,10 @@ public class DockerComposeProperties {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public boolean isUseContextClassLoader() {
|
||||
return this.useContextClassLoader;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void setUseContextClassLoader(boolean useContextClassLoader) {
|
||||
this.useContextClassLoader = useContextClassLoader;
|
||||
}
|
||||
|
||||
public List<String> getArguments() {
|
||||
return this.arguments;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.container.ContainerImageMetadata;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.docker.compose.core.RunningService;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeProperties;
|
||||
import org.springframework.boot.docker.compose.lifecycle.DockerComposeServicesReadyEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -48,30 +46,32 @@ import org.springframework.util.StringUtils;
|
||||
class DockerComposeServiceConnectionsApplicationListener
|
||||
implements ApplicationListener<DockerComposeServicesReadyEvent> {
|
||||
|
||||
DockerComposeServiceConnectionsApplicationListener() {
|
||||
private final ConnectionDetailsFactories factories;
|
||||
|
||||
DockerComposeServiceConnectionsApplicationListener() {
|
||||
this(new ConnectionDetailsFactories(null));
|
||||
}
|
||||
|
||||
DockerComposeServiceConnectionsApplicationListener(ConnectionDetailsFactories factories) {
|
||||
this.factories = factories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(DockerComposeServicesReadyEvent event) {
|
||||
ApplicationContext applicationContext = event.getSource();
|
||||
if (applicationContext instanceof BeanDefinitionRegistry registry) {
|
||||
Binder binder = Binder.get(applicationContext.getEnvironment());
|
||||
DockerComposeProperties properties = DockerComposeProperties.get(binder);
|
||||
boolean useContextClassLoader = properties.isUseContextClassLoader();
|
||||
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(useContextClassLoader);
|
||||
Environment environment = applicationContext.getEnvironment();
|
||||
registerConnectionDetails(registry, environment, event.getRunningServices(), factories);
|
||||
registerConnectionDetails(registry, environment, event.getRunningServices());
|
||||
}
|
||||
}
|
||||
|
||||
private void registerConnectionDetails(BeanDefinitionRegistry registry, Environment environment,
|
||||
List<RunningService> runningServices, ConnectionDetailsFactories factories) {
|
||||
List<RunningService> runningServices) {
|
||||
for (RunningService runningService : runningServices) {
|
||||
DockerComposeConnectionSource source = new DockerComposeConnectionSource(runningService, environment);
|
||||
factories.getConnectionDetails(source, false).forEach((connectionDetailsType, connectionDetails) -> {
|
||||
this.factories.getConnectionDetails(source, false).forEach((connectionDetailsType, connectionDetails) -> {
|
||||
register(registry, runningService, connectionDetailsType, connectionDetails);
|
||||
factories.getConnectionDetails(connectionDetails, false)
|
||||
this.factories.getConnectionDetails(connectionDetails, false)
|
||||
.forEach((adaptedType, adaptedDetails) -> register(registry, runningService, adaptedType,
|
||||
adaptedDetails));
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 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.
|
||||
@@ -42,7 +42,7 @@ class CustomRedisContainerConnectionDetailsFactoryTests {
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenRedisContainerWithCustomName() {
|
||||
ConnectionDetailsFactories factories = new ConnectionDetailsFactories();
|
||||
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(null);
|
||||
MergedAnnotation<ServiceConnection> annotation = MergedAnnotation.of(ServiceConnection.class,
|
||||
Map.of("value", ""));
|
||||
ContainerConnectionSource<RedisContainer> source = TestContainerConnectionSource.create("test", null,
|
||||
@@ -53,7 +53,7 @@ class CustomRedisContainerConnectionDetailsFactoryTests {
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenRedisStackContainerWithCustomName() {
|
||||
ConnectionDetailsFactories factories = new ConnectionDetailsFactories();
|
||||
ConnectionDetailsFactories factories = new ConnectionDetailsFactories(null);
|
||||
MergedAnnotation<ServiceConnection> annotation = MergedAnnotation.of(ServiceConnection.class,
|
||||
Map.of("value", ""));
|
||||
ContainerConnectionSource<RedisStackContainer> source = TestContainerConnectionSource.create("test", null,
|
||||
|
||||
@@ -57,7 +57,7 @@ class ServiceConnectionAutoConfigurationRegistrar implements ImportBeanDefinitio
|
||||
|
||||
private void registerBeanDefinitions(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry registry) {
|
||||
ConnectionDetailsRegistrar registrar = new ConnectionDetailsRegistrar(beanFactory,
|
||||
new ConnectionDetailsFactories());
|
||||
new ConnectionDetailsFactories(null));
|
||||
for (String beanName : beanFactory.getBeanNamesForType(Container.class)) {
|
||||
BeanDefinition beanDefinition = getBeanDefinition(beanFactory, beanName);
|
||||
MergedAnnotations annotations = (beanDefinition instanceof TestcontainerBeanDefinition testcontainerBeanDefinition)
|
||||
|
||||
@@ -47,7 +47,7 @@ class ServiceConnectionContextCustomizer implements ContextCustomizer {
|
||||
private final ConnectionDetailsFactories connectionDetailsFactories;
|
||||
|
||||
ServiceConnectionContextCustomizer(List<ContainerConnectionSource<?>> sources) {
|
||||
this(sources, new ConnectionDetailsFactories());
|
||||
this(sources, new ConnectionDetailsFactories(null));
|
||||
}
|
||||
|
||||
ServiceConnectionContextCustomizer(List<ContainerConnectionSource<?>> sources,
|
||||
|
||||
Reference in New Issue
Block a user