Merge branch '3.4.x'
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Has been cancelled
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Has been cancelled
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Has been cancelled
Details
Build and Deploy Snapshot / Verify (push) Has been cancelled
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Has been cancelled
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Has been cancelled
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Has been cancelled
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Has been cancelled
Details
Build and Deploy Snapshot / Verify (push) Has been cancelled
Details
This commit is contained in:
commit
a9b52c5892
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
* 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.build.autoconfigure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.asm.AnnotationVisitor;
|
||||
import org.springframework.asm.ClassReader;
|
||||
import org.springframework.asm.ClassVisitor;
|
||||
import org.springframework.asm.SpringAsmInfo;
|
||||
import org.springframework.asm.Type;
|
||||
|
||||
/**
|
||||
* An {@code @AutoConfiguration} class.
|
||||
*
|
||||
* @param name name of the auto-configuration class
|
||||
* @param before values of the {@code before} attribute
|
||||
* @param beforeName values of the {@code beforeName} attribute
|
||||
* @param after values of the {@code after} attribute
|
||||
* @param afterName values of the {@code afterName} attribute
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public record AutoConfigurationClass(String name, List<String> before, List<String> beforeName, List<String> after,
|
||||
List<String> afterName) {
|
||||
|
||||
private AutoConfigurationClass(String name, Map<String, List<String>> attributes) {
|
||||
this(name, attributes.getOrDefault("before", Collections.emptyList()),
|
||||
attributes.getOrDefault("beforeName", Collections.emptyList()),
|
||||
attributes.getOrDefault("after", Collections.emptyList()),
|
||||
attributes.getOrDefault("afterName", Collections.emptyList()));
|
||||
}
|
||||
|
||||
static AutoConfigurationClass of(File classFile) {
|
||||
try (FileInputStream input = new FileInputStream(classFile)) {
|
||||
ClassReader classReader = new ClassReader(input);
|
||||
AutoConfigurationClassVisitor visitor = new AutoConfigurationClassVisitor();
|
||||
classReader.accept(visitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
|
||||
return visitor.autoConfigurationClass;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AutoConfigurationClassVisitor extends ClassVisitor {
|
||||
|
||||
private AutoConfigurationClass autoConfigurationClass;
|
||||
|
||||
private String name;
|
||||
|
||||
private AutoConfigurationClassVisitor() {
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName,
|
||||
String[] interfaces) {
|
||||
this.name = Type.getObjectType(name).getClassName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
|
||||
String annotationClassName = Type.getType(descriptor).getClassName();
|
||||
if ("org.springframework.boot.autoconfigure.AutoConfiguration".equals(annotationClassName)) {
|
||||
return new AutoConfigurationAnnotationVisitor();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final class AutoConfigurationAnnotationVisitor extends AnnotationVisitor {
|
||||
|
||||
private Map<String, List<String>> attributes = new HashMap<>();
|
||||
|
||||
private static final Set<String> INTERESTING_ATTRIBUTES = Set.of("before", "beforeName", "after",
|
||||
"afterName");
|
||||
|
||||
private AutoConfigurationAnnotationVisitor() {
|
||||
super(SpringAsmInfo.ASM_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
AutoConfigurationClassVisitor.this.autoConfigurationClass = new AutoConfigurationClass(
|
||||
AutoConfigurationClassVisitor.this.name, this.attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(String attributeName) {
|
||||
if (INTERESTING_ATTRIBUTES.contains(attributeName)) {
|
||||
return new AnnotationVisitor(SpringAsmInfo.ASM_VERSION) {
|
||||
|
||||
@Override
|
||||
public void visit(String name, Object value) {
|
||||
if (value instanceof Type type) {
|
||||
value = type.getClassName();
|
||||
}
|
||||
AutoConfigurationAnnotationVisitor.this.attributes
|
||||
.computeIfAbsent(attributeName, (n) -> new ArrayList<>())
|
||||
.add(Objects.toString(value));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
* 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.build.autoconfigure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.FileTree;
|
||||
import org.gradle.api.tasks.InputFiles;
|
||||
import org.gradle.api.tasks.PathSensitive;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.SkipWhenEmpty;
|
||||
|
||||
/**
|
||||
* A {@link Task} that uses a project's auto-configuration imports.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AutoConfigurationImportsTask extends DefaultTask {
|
||||
|
||||
static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports";
|
||||
|
||||
private FileCollection sourceFiles = getProject().getObjects().fileCollection();
|
||||
|
||||
@InputFiles
|
||||
@SkipWhenEmpty
|
||||
@PathSensitive(PathSensitivity.RELATIVE)
|
||||
public FileTree getSource() {
|
||||
return this.sourceFiles.getAsFileTree().matching((filter) -> filter.include(IMPORTS_FILE));
|
||||
}
|
||||
|
||||
public void setSource(Object source) {
|
||||
this.sourceFiles = getProject().getObjects().fileCollection().from(source);
|
||||
}
|
||||
|
||||
protected List<String> loadImports() {
|
||||
File importsFile = getSource().getSingleFile();
|
||||
try {
|
||||
return Files.readAllLines(importsFile.toPath());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -16,31 +16,25 @@
|
|||
|
||||
package org.springframework.boot.build.autoconfigure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.lang.ArchCondition;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import com.tngtech.archunit.lang.ConditionEvents;
|
||||
import com.tngtech.archunit.lang.SimpleConditionEvent;
|
||||
import com.tngtech.archunit.lang.syntax.ArchRuleDefinition;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ConfigurationContainer;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
|
||||
import org.springframework.boot.build.DeployedPlugin;
|
||||
import org.springframework.boot.build.architecture.ArchitectureCheck;
|
||||
import org.springframework.boot.build.architecture.ArchitecturePlugin;
|
||||
import org.springframework.boot.build.optional.OptionalDependenciesPlugin;
|
||||
|
||||
/**
|
||||
* {@link Plugin} for projects that define auto-configuration. When applied, the plugin
|
||||
|
@ -52,12 +46,7 @@ import org.springframework.boot.build.architecture.ArchitecturePlugin;
|
|||
* <li>Defines a task that produces metadata describing the auto-configuration. The
|
||||
* metadata is made available as an artifact in the {@code autoConfigurationMetadata}
|
||||
* configuration.
|
||||
* <li>Reacts to the {@link ArchitecturePlugin} being applied and:
|
||||
* <ul>
|
||||
* <li>Adds a rule to the {@code checkArchitectureMain} task to verify that all
|
||||
* {@code AutoConfiguration} classes are listed in the {@code AutoConfiguration.imports}
|
||||
* file.
|
||||
* </ul>
|
||||
* <li>Add checks to ensure import files and annotations are correct</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
|
@ -70,102 +59,103 @@ public class AutoConfigurationPlugin implements Plugin<Project> {
|
|||
*/
|
||||
public static final String AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME = "autoConfigurationMetadata";
|
||||
|
||||
private static final String AUTO_CONFIGURATION_IMPORTS_PATH = "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports";
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
project.getPlugins().apply(DeployedPlugin.class);
|
||||
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> {
|
||||
Configuration annotationProcessors = project.getConfigurations()
|
||||
.getByName(JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME);
|
||||
annotationProcessors.getDependencies()
|
||||
.add(project.getDependencies()
|
||||
.project(Collections.singletonMap("path",
|
||||
":spring-boot-project:spring-boot-tools:spring-boot-autoconfigure-processor")));
|
||||
annotationProcessors.getDependencies()
|
||||
.add(project.getDependencies()
|
||||
.project(Collections.singletonMap("path",
|
||||
":spring-boot-project:spring-boot-tools:spring-boot-configuration-processor")));
|
||||
project.getTasks().register("autoConfigurationMetadata", AutoConfigurationMetadata.class, (task) -> {
|
||||
SourceSet main = project.getExtensions()
|
||||
.getByType(JavaPluginExtension.class)
|
||||
.getSourceSets()
|
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
task.setSourceSet(main);
|
||||
task.dependsOn(main.getClassesTaskName());
|
||||
task.getOutputFile()
|
||||
.set(project.getLayout().getBuildDirectory().file("auto-configuration-metadata.properties"));
|
||||
project.getArtifacts()
|
||||
.add(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME, task.getOutputFile(),
|
||||
(artifact) -> artifact.builtBy(task));
|
||||
project.getPlugins().withType(JavaPlugin.class, (javaPlugin) -> new Configurer(project).configure());
|
||||
}
|
||||
|
||||
private static class Configurer {
|
||||
|
||||
private final Project project;
|
||||
|
||||
private SourceSet main;
|
||||
|
||||
Configurer(Project project) {
|
||||
this.project = project;
|
||||
this.main = project.getExtensions()
|
||||
.getByType(JavaPluginExtension.class)
|
||||
.getSourceSets()
|
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
}
|
||||
|
||||
void configure() {
|
||||
addAnnotationProcessorsDependencies();
|
||||
TaskContainer tasks = this.project.getTasks();
|
||||
ConfigurationContainer configurations = this.project.getConfigurations();
|
||||
tasks.register("autoConfigurationMetadata", AutoConfigurationMetadata.class,
|
||||
this::configureAutoConfigurationMetadata);
|
||||
TaskProvider<CheckAutoConfigurationImports> checkAutoConfigurationImports = tasks.register(
|
||||
"checkAutoConfigurationImports", CheckAutoConfigurationImports.class,
|
||||
this::configureCheckAutoConfigurationImports);
|
||||
Configuration requiredClasspath = configurations.create("autoConfigurationRequiredClasspath")
|
||||
.extendsFrom(configurations.getByName(this.main.getImplementationConfigurationName()),
|
||||
configurations.getByName(this.main.getRuntimeOnlyConfigurationName()));
|
||||
requiredClasspath.getDependencies()
|
||||
.add(projectDependency(":spring-boot-project:spring-boot-autoconfigure"));
|
||||
TaskProvider<CheckAutoConfigurationClasses> checkAutoConfigurationClasses = tasks.register(
|
||||
"checkAutoConfigurationClasses", CheckAutoConfigurationClasses.class,
|
||||
(task) -> configureCheckAutoConfigurationClasses(requiredClasspath, task));
|
||||
this.project.getPlugins()
|
||||
.withType(OptionalDependenciesPlugin.class,
|
||||
(plugin) -> configureCheckAutoConfigurationClassesForOptionalDependencies(configurations,
|
||||
checkAutoConfigurationClasses));
|
||||
this.project.getTasks()
|
||||
.getByName(JavaBasePlugin.CHECK_TASK_NAME)
|
||||
.dependsOn(checkAutoConfigurationImports, checkAutoConfigurationClasses);
|
||||
}
|
||||
|
||||
private void addAnnotationProcessorsDependencies() {
|
||||
this.project.getConfigurations()
|
||||
.getByName(JavaPlugin.ANNOTATION_PROCESSOR_CONFIGURATION_NAME)
|
||||
.getDependencies()
|
||||
.addAll(projectDependencies(
|
||||
":spring-boot-project:spring-boot-tools:spring-boot-autoconfigure-processor",
|
||||
":spring-boot-project:spring-boot-tools:spring-boot-configuration-processor"));
|
||||
}
|
||||
|
||||
private void configureAutoConfigurationMetadata(AutoConfigurationMetadata task) {
|
||||
task.setSourceSet(this.main);
|
||||
task.dependsOn(this.main.getClassesTaskName());
|
||||
task.getOutputFile()
|
||||
.set(this.project.getLayout().getBuildDirectory().file("auto-configuration-metadata.properties"));
|
||||
this.project.getArtifacts()
|
||||
.add(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME, task.getOutputFile(),
|
||||
(artifact) -> artifact.builtBy(task));
|
||||
}
|
||||
|
||||
private void configureCheckAutoConfigurationImports(CheckAutoConfigurationImports task) {
|
||||
task.setSource(this.main.getResources());
|
||||
task.setClasspath(this.main.getOutput().getClassesDirs());
|
||||
task.setDescription(
|
||||
"Checks the %s file of the main source set.".formatted(AutoConfigurationImportsTask.IMPORTS_FILE));
|
||||
}
|
||||
|
||||
private void configureCheckAutoConfigurationClasses(Configuration requiredClasspath,
|
||||
CheckAutoConfigurationClasses task) {
|
||||
task.setSource(this.main.getResources());
|
||||
task.setClasspath(this.main.getOutput().getClassesDirs());
|
||||
task.setRequiredDependencies(requiredClasspath);
|
||||
task.setDescription("Checks the auto-configuration classes of the main source set.");
|
||||
}
|
||||
|
||||
private void configureCheckAutoConfigurationClassesForOptionalDependencies(
|
||||
ConfigurationContainer configurations,
|
||||
TaskProvider<CheckAutoConfigurationClasses> checkAutoConfigurationClasses) {
|
||||
checkAutoConfigurationClasses.configure((check) -> {
|
||||
Configuration optionalClasspath = configurations.create("autoConfigurationOptionalClassPath")
|
||||
.extendsFrom(configurations.getByName(OptionalDependenciesPlugin.OPTIONAL_CONFIGURATION_NAME));
|
||||
check.setOptionalDependencies(optionalClasspath);
|
||||
});
|
||||
project.getPlugins()
|
||||
.withType(ArchitecturePlugin.class, (plugin) -> configureArchitecturePluginTasks(project));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void configureArchitecturePluginTasks(Project project) {
|
||||
project.getTasks().configureEach((task) -> {
|
||||
if ("checkArchitectureMain".equals(task.getName()) && task instanceof ArchitectureCheck architectureCheck) {
|
||||
configureCheckArchitectureMain(project, architectureCheck);
|
||||
}
|
||||
});
|
||||
}
|
||||
private Set<Dependency> projectDependencies(String... paths) {
|
||||
return Arrays.stream(paths).map((path) -> projectDependency(path)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void configureCheckArchitectureMain(Project project, ArchitectureCheck architectureCheck) {
|
||||
SourceSet main = project.getExtensions()
|
||||
.getByType(JavaPluginExtension.class)
|
||||
.getSourceSets()
|
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
File resourcesDirectory = main.getOutput().getResourcesDir();
|
||||
architectureCheck.dependsOn(main.getProcessResourcesTaskName());
|
||||
architectureCheck.getInputs()
|
||||
.files(resourcesDirectory)
|
||||
.optional()
|
||||
.withPathSensitivity(PathSensitivity.RELATIVE);
|
||||
architectureCheck.getRules()
|
||||
.add(allClassesAnnotatedWithAutoConfigurationShouldBeListedInAutoConfigurationImports(
|
||||
autoConfigurationImports(project, resourcesDirectory)));
|
||||
}
|
||||
|
||||
private ArchRule allClassesAnnotatedWithAutoConfigurationShouldBeListedInAutoConfigurationImports(
|
||||
Provider<AutoConfigurationImports> imports) {
|
||||
return ArchRuleDefinition.classes()
|
||||
.that()
|
||||
.areAnnotatedWith("org.springframework.boot.autoconfigure.AutoConfiguration")
|
||||
.should(beListedInAutoConfigurationImports(imports))
|
||||
.allowEmptyShould(true);
|
||||
}
|
||||
|
||||
private ArchCondition<JavaClass> beListedInAutoConfigurationImports(Provider<AutoConfigurationImports> imports) {
|
||||
return new ArchCondition<>("be listed in " + AUTO_CONFIGURATION_IMPORTS_PATH) {
|
||||
|
||||
@Override
|
||||
public void check(JavaClass item, ConditionEvents events) {
|
||||
AutoConfigurationImports autoConfigurationImports = imports.get();
|
||||
if (!autoConfigurationImports.imports.contains(item.getName())) {
|
||||
events.add(SimpleConditionEvent.violated(item,
|
||||
item.getName() + " was not listed in " + autoConfigurationImports.importsFile));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private Provider<AutoConfigurationImports> autoConfigurationImports(Project project, File resourcesDirectory) {
|
||||
Path importsFile = new File(resourcesDirectory, AUTO_CONFIGURATION_IMPORTS_PATH).toPath();
|
||||
return project.provider(() -> {
|
||||
try {
|
||||
return new AutoConfigurationImports(project.getProjectDir().toPath().relativize(importsFile),
|
||||
Files.readAllLines(importsFile));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException("Failed to read AutoConfiguration.imports", ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private record AutoConfigurationImports(Path importsFile, List<String> imports) {
|
||||
private Dependency projectDependency(String path) {
|
||||
return this.project.getDependencies().project(Collections.singletonMap("path", path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* 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.
|
||||
* 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.build.autoconfigure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.provider.SetProperty;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.VerificationException;
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin;
|
||||
|
||||
/**
|
||||
* Task to check a project's {@code @AutoConfiguration} classes.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class CheckAutoConfigurationClasses extends AutoConfigurationImportsTask {
|
||||
|
||||
private FileCollection classpath = getProject().getObjects().fileCollection();
|
||||
|
||||
private FileCollection optionalDependencies = getProject().getObjects().fileCollection();
|
||||
|
||||
private FileCollection requiredDependencies = getProject().getObjects().fileCollection();
|
||||
|
||||
private SetProperty<String> optionalDependencyClassNames = getProject().getObjects().setProperty(String.class);
|
||||
|
||||
private SetProperty<String> requiredDependencyClassNames = getProject().getObjects().setProperty(String.class);
|
||||
|
||||
public CheckAutoConfigurationClasses() {
|
||||
getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
|
||||
setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
|
||||
this.optionalDependencyClassNames.set(getProject().provider(() -> classNamesOf(this.optionalDependencies)));
|
||||
this.requiredDependencyClassNames.set(getProject().provider(() -> classNamesOf(this.requiredDependencies)));
|
||||
}
|
||||
|
||||
private static List<String> classNamesOf(FileCollection classpath) {
|
||||
return classpath.getFiles().stream().flatMap((file) -> {
|
||||
try (JarFile jarFile = new JarFile(file)) {
|
||||
return Collections.list(jarFile.entries())
|
||||
.stream()
|
||||
.filter((entry) -> !entry.isDirectory())
|
||||
.map(JarEntry::getName)
|
||||
.filter((entryName) -> entryName.endsWith(".class"))
|
||||
.map((entryName) -> entryName.substring(0, entryName.length() - ".class".length()))
|
||||
.map((entryName) -> entryName.replace("/", "."));
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@Classpath
|
||||
public FileCollection getClasspath() {
|
||||
return this.classpath;
|
||||
}
|
||||
|
||||
public void setClasspath(Object classpath) {
|
||||
this.classpath = getProject().getObjects().fileCollection().from(classpath);
|
||||
}
|
||||
|
||||
@Classpath
|
||||
public FileCollection getOptionalDependencies() {
|
||||
return this.optionalDependencies;
|
||||
}
|
||||
|
||||
public void setOptionalDependencies(Object classpath) {
|
||||
this.optionalDependencies = getProject().getObjects().fileCollection().from(classpath);
|
||||
}
|
||||
|
||||
@Classpath
|
||||
public FileCollection getRequiredDependencies() {
|
||||
return this.requiredDependencies;
|
||||
}
|
||||
|
||||
public void setRequiredDependencies(Object classpath) {
|
||||
this.requiredDependencies = getProject().getObjects().fileCollection().from(classpath);
|
||||
}
|
||||
|
||||
@OutputDirectory
|
||||
public abstract DirectoryProperty getOutputDirectory();
|
||||
|
||||
@TaskAction
|
||||
void execute() {
|
||||
Map<String, List<String>> problems = new TreeMap<>();
|
||||
Set<String> optionalOnlyClassNames = new HashSet<>(this.optionalDependencyClassNames.get());
|
||||
Set<String> requiredClassNames = this.requiredDependencyClassNames.get();
|
||||
optionalOnlyClassNames.removeAll(requiredClassNames);
|
||||
classFiles().forEach((classFile) -> {
|
||||
AutoConfigurationClass autoConfigurationClass = AutoConfigurationClass.of(classFile);
|
||||
if (autoConfigurationClass != null) {
|
||||
check(autoConfigurationClass, optionalOnlyClassNames, requiredClassNames, problems);
|
||||
}
|
||||
});
|
||||
File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
|
||||
writeReport(problems, outputFile);
|
||||
if (!problems.isEmpty()) {
|
||||
throw new VerificationException(
|
||||
"Auto-configuration class check failed. See '%s' for details".formatted(outputFile));
|
||||
}
|
||||
}
|
||||
|
||||
private List<File> classFiles() {
|
||||
List<File> classFiles = new ArrayList<>();
|
||||
for (File root : this.classpath.getFiles()) {
|
||||
try (Stream<Path> files = Files.walk(root.toPath())) {
|
||||
files.forEach((file) -> {
|
||||
if (Files.isRegularFile(file) && file.getFileName().toString().endsWith(".class")) {
|
||||
classFiles.add(file.toFile());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
return classFiles;
|
||||
}
|
||||
|
||||
private void check(AutoConfigurationClass autoConfigurationClass, Set<String> optionalOnlyClassNames,
|
||||
Set<String> requiredClassNames, Map<String, List<String>> problems) {
|
||||
if (!autoConfigurationClass.name().endsWith("AutoConfiguration")) {
|
||||
problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>())
|
||||
.add("Name of a class annotated with @AutoConfiguration should end with AutoConfiguration");
|
||||
}
|
||||
autoConfigurationClass.before().forEach((before) -> {
|
||||
if (optionalOnlyClassNames.contains(before)) {
|
||||
problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>())
|
||||
.add("before '%s' is from an optional dependency and should be declared in beforeName"
|
||||
.formatted(before));
|
||||
}
|
||||
});
|
||||
autoConfigurationClass.beforeName().forEach((beforeName) -> {
|
||||
if (!optionalOnlyClassNames.contains(beforeName)) {
|
||||
String problem = requiredClassNames.contains(beforeName)
|
||||
? "beforeName '%s' is from a required dependency and should be declared in before"
|
||||
.formatted(beforeName)
|
||||
: "beforeName '%s' not found".formatted(beforeName);
|
||||
problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>()).add(problem);
|
||||
}
|
||||
});
|
||||
autoConfigurationClass.after().forEach((after) -> {
|
||||
if (optionalOnlyClassNames.contains(after)) {
|
||||
problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>())
|
||||
.add("after '%s' is from an optional dependency and should be declared in afterName"
|
||||
.formatted(after));
|
||||
}
|
||||
});
|
||||
autoConfigurationClass.afterName().forEach((afterName) -> {
|
||||
if (!optionalOnlyClassNames.contains(afterName)) {
|
||||
String problem = requiredClassNames.contains(afterName)
|
||||
? "afterName '%s' is from a required dependency and should be declared in after"
|
||||
.formatted(afterName)
|
||||
: "afterName '%s' not found".formatted(afterName);
|
||||
problems.computeIfAbsent(autoConfigurationClass.name(), (name) -> new ArrayList<>()).add(problem);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void writeReport(Map<String, List<String>> problems, File outputFile) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
StringBuilder report = new StringBuilder();
|
||||
if (!problems.isEmpty()) {
|
||||
report.append("Found auto-configuration class problems:%n".formatted());
|
||||
problems.forEach((className, classProblems) -> {
|
||||
report.append(" - %s:%n".formatted(className));
|
||||
classProblems.forEach((problem) -> report.append(" - %s%n".formatted(problem)));
|
||||
});
|
||||
}
|
||||
try {
|
||||
Files.writeString(outputFile.toPath(), report.toString(), StandardOpenOption.CREATE,
|
||||
StandardOpenOption.TRUNCATE_EXISTING);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright 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.
|
||||
* 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.build.autoconfigure;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.VerificationException;
|
||||
import org.gradle.language.base.plugins.LifecycleBasePlugin;
|
||||
|
||||
/**
|
||||
* Task to check the contents of a project's
|
||||
* {@code META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports}
|
||||
* file.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class CheckAutoConfigurationImports extends AutoConfigurationImportsTask {
|
||||
|
||||
private FileCollection classpath = getProject().getObjects().fileCollection();
|
||||
|
||||
public CheckAutoConfigurationImports() {
|
||||
getOutputDirectory().convention(getProject().getLayout().getBuildDirectory().dir(getName()));
|
||||
setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
|
||||
}
|
||||
|
||||
@Classpath
|
||||
public FileCollection getClasspath() {
|
||||
return this.classpath;
|
||||
}
|
||||
|
||||
public void setClasspath(Object classpath) {
|
||||
this.classpath = getProject().getObjects().fileCollection().from(classpath);
|
||||
}
|
||||
|
||||
@OutputDirectory
|
||||
public abstract DirectoryProperty getOutputDirectory();
|
||||
|
||||
@TaskAction
|
||||
void execute() {
|
||||
File importsFile = getSource().getSingleFile();
|
||||
check(importsFile);
|
||||
}
|
||||
|
||||
private void check(File importsFile) {
|
||||
List<String> imports = loadImports();
|
||||
List<String> problems = new ArrayList<>();
|
||||
for (String imported : imports) {
|
||||
File classFile = find(imported);
|
||||
if (classFile == null) {
|
||||
problems.add("'%s' was not found".formatted(imported));
|
||||
}
|
||||
else if (!correctlyAnnotated(classFile)) {
|
||||
problems.add("'%s' is not annotated with @AutoConfiguration".formatted(imported));
|
||||
}
|
||||
}
|
||||
List<String> sortedValues = new ArrayList<>(imports);
|
||||
Collections.sort(sortedValues);
|
||||
if (!sortedValues.equals(imports)) {
|
||||
File sortedOutputFile = getOutputDirectory().file("sorted-" + importsFile.getName()).get().getAsFile();
|
||||
writeString(sortedOutputFile,
|
||||
sortedValues.stream().collect(Collectors.joining(System.lineSeparator())) + System.lineSeparator());
|
||||
problems.add("Entries should be sorted alphabetically (expect content written to "
|
||||
+ sortedOutputFile.getAbsolutePath() + ")");
|
||||
}
|
||||
File outputFile = getOutputDirectory().file("failure-report.txt").get().getAsFile();
|
||||
writeReport(importsFile, problems, outputFile);
|
||||
if (!problems.isEmpty()) {
|
||||
throw new VerificationException("%s check failed. See '%s' for details"
|
||||
.formatted(AutoConfigurationImportsTask.IMPORTS_FILE, outputFile));
|
||||
}
|
||||
}
|
||||
|
||||
private File find(String className) {
|
||||
for (File root : this.classpath.getFiles()) {
|
||||
String classFilePath = className.replace(".", "/") + ".class";
|
||||
File classFile = new File(root, classFilePath);
|
||||
if (classFile.isFile()) {
|
||||
return classFile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean correctlyAnnotated(File classFile) {
|
||||
return AutoConfigurationClass.of(classFile) != null;
|
||||
}
|
||||
|
||||
private void writeReport(File importsFile, List<String> problems, File outputFile) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
StringBuilder report = new StringBuilder();
|
||||
if (!problems.isEmpty()) {
|
||||
report.append("Found problems in '%s':%n".formatted(importsFile));
|
||||
problems.forEach((problem) -> report.append(" - %s%n".formatted(problem)));
|
||||
}
|
||||
writeString(outputFile, report.toString());
|
||||
}
|
||||
|
||||
private void writeString(File file, String content) {
|
||||
try {
|
||||
Files.writeString(file.toPath(), content);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -80,14 +80,12 @@ public abstract class DocumentAutoConfigurationClasses extends DefaultTask {
|
|||
writer.println("[cols=\"4,1\"]");
|
||||
writer.println("|===");
|
||||
writer.println("| Configuration Class | Links");
|
||||
|
||||
for (AutoConfigurationClass autoConfigurationClass : autoConfigurationClasses.classes) {
|
||||
writer.println();
|
||||
writer.printf("| {code-spring-boot}/spring-boot-project/%s/src/main/java/%s.java[`%s`]%n",
|
||||
autoConfigurationClasses.module, autoConfigurationClass.path, autoConfigurationClass.name);
|
||||
writer.printf("| xref:api:java/%s.html[javadoc]%n", autoConfigurationClass.path);
|
||||
}
|
||||
|
||||
writer.println("|===");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.jackson.EndpointObjectMapper;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
|
||||
/**
|
||||
|
@ -36,8 +35,7 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
|||
* @author Phillip Webb
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigureAfter(JacksonAutoConfiguration.class)
|
||||
@AutoConfiguration(after = JacksonAutoConfiguration.class)
|
||||
public class JacksonEndpointAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -30,12 +30,11 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|||
import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
@ -46,8 +45,7 @@ import org.springframework.util.StringUtils;
|
|||
* @author Stephane Nicoll
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigureAfter({ MetricsAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
|
||||
@AutoConfiguration(after = { MetricsAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
|
||||
SimpleMetricsExportAutoConfiguration.class })
|
||||
@ConditionalOnClass({ EntityManagerFactory.class, SessionFactory.class, HibernateMetrics.class, MeterRegistry.class })
|
||||
@ConditionalOnBean({ EntityManagerFactory.class, MeterRegistry.class })
|
||||
|
|
|
@ -7,14 +7,18 @@ org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfigurat
|
|||
org.springframework.boot.actuate.autoconfigure.cache.CachesEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.cassandra.CassandraHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.cassandra.CassandraReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryActuatorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive.ReactiveCloudFoundryActuatorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet.CloudFoundryActuatorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.context.ShutdownEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.couchbase.CouchbaseHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.couchbase.CouchbaseReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.elasticsearch.ElasticsearchReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.mongo.MongoHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.mongo.MongoReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.redis.RedisHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.redis.RedisReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.elasticsearch.ElasticsearchRestHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointAutoConfiguration
|
||||
|
@ -70,8 +74,6 @@ org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetri
|
|||
org.springframework.boot.actuate.autoconfigure.metrics.export.stackdriver.StackdriverMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.statsd.StatsdMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.export.wavefront.WavefrontMetricsExportAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetricsAutoConfiguration
|
||||
|
@ -81,30 +83,28 @@ org.springframework.boot.actuate.autoconfigure.metrics.r2dbc.ConnectionPoolMetri
|
|||
org.springframework.boot.actuate.autoconfigure.metrics.redis.LettuceMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.startup.StartupTimeMetricsListenerAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.web.jetty.JettyMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.web.reactive.WebFluxObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.mongo.MongoHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.mongo.MongoReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.neo4j.Neo4jHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.batch.BatchObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.graphql.GraphQlObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.web.reactive.WebFluxObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.quartz.QuartzEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.r2dbc.ConnectionFactoryHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.r2dbc.R2dbcObservationAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.redis.RedisHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.data.redis.RedisReactiveHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.sbom.SbomEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.session.SessionsEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.startup.StartupEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.ssl.SslHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.ssl.SslObservabilityAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.startup.StartupEndpointAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.BraveAutoConfiguration
|
||||
org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration
|
||||
|
|
|
@ -47,7 +47,6 @@ class ObservationRegistryConfigurerIntegrationTests {
|
|||
CalledCustomizers calledCustomizers = context.getBean(CalledCustomizers.class);
|
||||
Customizer1 customizer1 = context.getBean(Customizer1.class);
|
||||
Customizer2 customizer2 = context.getBean(Customizer2.class);
|
||||
|
||||
assertThat(calledCustomizers.getCustomizers()).containsExactly(customizer1, customizer2);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class HttpExchangesFilter extends OncePerRequestFilter implements Ordered
|
|||
private final Set<Include> includes;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
* Create a new {@link HttpExchangesFilter} instance.
|
||||
* @param repository the repository used to record events
|
||||
* @param includes the include options
|
||||
*/
|
||||
|
|
|
@ -18,10 +18,10 @@ package org.springframework.boot.autoconfigure.reactor;
|
|||
|
||||
import reactor.core.publisher.Hooks;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Reactor.
|
||||
|
@ -29,7 +29,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
* @author Brian Clozel
|
||||
* @since 3.2.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass(Hooks.class)
|
||||
@EnableConfigurationProperties(ReactorProperties.class)
|
||||
public class ReactorAutoConfiguration {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration
|
||||
|
@ -45,10 +46,10 @@ org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClient
|
|||
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.GraphQlAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQueryByExampleAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQuerydslAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlQueryByExampleAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlQuerydslAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQueryByExampleAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.data.GraphQlReactiveQuerydslAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.reactive.GraphQlWebFluxAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.rsocket.GraphQlRSocketAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.graphql.rsocket.RSocketGraphQlClientAutoConfiguration
|
||||
|
@ -69,23 +70,22 @@ org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration
|
|||
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration
|
||||
|
@ -106,23 +106,23 @@ org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration
|
|||
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientWebSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientWebSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerJwtAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientWebSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientWebSecurityAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.security.oauth2.server.servlet.OAuth2AuthorizationServerJwtAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration
|
||||
|
@ -144,13 +144,13 @@ org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfig
|
|||
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration
|
||||
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
|
||||
|
|
Loading…
Reference in New Issue