Skip to content

Commit c0f1f64

Browse files
committed
Make auto-configurations final and remove public members
Closes gh-32883
1 parent a7e0689 commit c0f1f64

File tree

334 files changed

+891
-811
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

334 files changed

+891
-811
lines changed

buildSrc/src/main/java/org/springframework/boot/build/architecture/ArchitectureRules.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,22 @@
2222
import java.util.List;
2323
import java.util.Map;
2424
import java.util.Objects;
25+
import java.util.Set;
2526
import java.util.function.BiConsumer;
2627
import java.util.function.Predicate;
2728
import java.util.function.Supplier;
2829
import java.util.stream.Collectors;
30+
import java.util.stream.Stream;
2931

3032
import com.tngtech.archunit.base.DescribedPredicate;
3133
import com.tngtech.archunit.core.domain.AccessTarget.CodeUnitCallTarget;
3234
import com.tngtech.archunit.core.domain.JavaAnnotation;
3335
import com.tngtech.archunit.core.domain.JavaCall;
3436
import com.tngtech.archunit.core.domain.JavaClass;
3537
import com.tngtech.archunit.core.domain.JavaClass.Predicates;
38+
import com.tngtech.archunit.core.domain.JavaConstructor;
39+
import com.tngtech.archunit.core.domain.JavaField;
40+
import com.tngtech.archunit.core.domain.JavaMember;
3641
import com.tngtech.archunit.core.domain.JavaMethod;
3742
import com.tngtech.archunit.core.domain.JavaModifier;
3843
import com.tngtech.archunit.core.domain.JavaParameter;
@@ -68,6 +73,8 @@
6873
*/
6974
final class ArchitectureRules {
7075

76+
private static final String AUTOCONFIGURATION_ANNOTATION = "org.springframework.boot.autoconfigure.AutoConfiguration";
77+
7178
private ArchitectureRules() {
7279
}
7380

@@ -98,6 +105,8 @@ static List<ArchRule> standard() {
98105
rules.add(methodLevelConfigurationPropertiesShouldNotSpecifyOnlyPrefixAttribute());
99106
rules.add(conditionsShouldNotBePublic());
100107
rules.add(allConfigurationPropertiesBindingBeanMethodsShouldBeStatic());
108+
rules.add(autoConfigurationClassesShouldBePublicAndFinal());
109+
rules.add(autoConfigurationClassesShouldHaveNoPublicMembers());
101110
return List.copyOf(rules);
102111
}
103112

@@ -319,6 +328,63 @@ private static ArchRule allConfigurationPropertiesBindingBeanMethodsShouldBeStat
319328
.allowEmptyShould(true);
320329
}
321330

331+
private static ArchRule autoConfigurationClassesShouldBePublicAndFinal() {
332+
return ArchRuleDefinition.classes()
333+
.that()
334+
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
335+
.should()
336+
.bePublic()
337+
.andShould()
338+
.haveModifier(JavaModifier.FINAL)
339+
.allowEmptyShould(true);
340+
}
341+
342+
private static ArchRule autoConfigurationClassesShouldHaveNoPublicMembers() {
343+
return ArchRuleDefinition.members()
344+
.that()
345+
.areDeclaredInClassesThat()
346+
.areAnnotatedWith(AUTOCONFIGURATION_ANNOTATION)
347+
.and(areNotDefaultConstructors())
348+
.and(areNotConstants())
349+
.and(dontOverridePublicMethods())
350+
.should()
351+
.notBePublic()
352+
.allowEmptyShould(true);
353+
}
354+
355+
private static DescribedPredicate<? super JavaMember> dontOverridePublicMethods() {
356+
OverridesPublicMethod<JavaMember> predicate = new OverridesPublicMethod<>();
357+
return DescribedPredicate.describe("don't override public methods", (member) -> !predicate.test(member));
358+
}
359+
360+
private static DescribedPredicate<JavaMember> areNotDefaultConstructors() {
361+
return DescribedPredicate.describe("aren't default constructors",
362+
(member) -> !areDefaultConstructors().test(member));
363+
}
364+
365+
private static DescribedPredicate<JavaMember> areDefaultConstructors() {
366+
return DescribedPredicate.describe("are default constructors", (member) -> {
367+
if (!(member instanceof JavaConstructor constructor)) {
368+
return false;
369+
}
370+
return constructor.getParameters().isEmpty();
371+
});
372+
}
373+
374+
private static DescribedPredicate<JavaMember> areNotConstants() {
375+
return DescribedPredicate.describe("aren't constants", (member) -> !areConstants().test(member));
376+
}
377+
378+
private static DescribedPredicate<JavaMember> areConstants() {
379+
return DescribedPredicate.describe("are constants", (member) -> {
380+
if (member instanceof JavaField field) {
381+
Set<JavaModifier> modifiers = field.getModifiers();
382+
return modifiers.contains(JavaModifier.STATIC) && modifiers.contains(JavaModifier.FINAL);
383+
}
384+
return false;
385+
});
386+
}
387+
322388
private static boolean containsOnlySingleType(JavaType[] types, JavaType type) {
323389
return types.length == 1 && type.equals(types[0]);
324390
}
@@ -391,4 +457,39 @@ private static String shouldUse(String string) {
391457
return string + " should be used instead";
392458
}
393459

460+
private static class OverridesPublicMethod<T extends JavaMember> extends DescribedPredicate<T> {
461+
462+
OverridesPublicMethod() {
463+
super("overrides public method");
464+
}
465+
466+
@Override
467+
public boolean test(T member) {
468+
if (!(member instanceof JavaMethod javaMethod)) {
469+
return false;
470+
}
471+
Stream<JavaMethod> superClassMethods = member.getOwner()
472+
.getAllRawSuperclasses()
473+
.stream()
474+
.flatMap((superClass) -> superClass.getMethods().stream());
475+
Stream<JavaMethod> interfaceMethods = member.getOwner()
476+
.getAllRawInterfaces()
477+
.stream()
478+
.flatMap((iface) -> iface.getMethods().stream());
479+
return Stream.concat(superClassMethods, interfaceMethods)
480+
.anyMatch((superMethod) -> isPublic(superMethod) && isOverridden(superMethod, javaMethod));
481+
}
482+
483+
private boolean isPublic(JavaMethod method) {
484+
return method.getModifiers().contains(JavaModifier.PUBLIC);
485+
}
486+
487+
private boolean isOverridden(JavaMethod superMethod, JavaMethod method) {
488+
return superMethod.getName().equals(method.getName())
489+
&& superMethod.getRawParameterTypes().size() == method.getRawParameterTypes().size()
490+
&& superMethod.getDescriptor().equals(method.getDescriptor());
491+
}
492+
493+
}
494+
394495
}

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
*/
4141
@AutoConfiguration(after = JmxAutoConfiguration.class)
4242
@ConditionalOnBooleanProperty("spring.application.admin.enabled")
43-
public class SpringApplicationAdminJmxAutoConfiguration {
43+
public final class SpringApplicationAdminJmxAutoConfiguration {
4444

4545
/**
4646
* The property to use to customize the {@code ObjectName} of the application admin
@@ -55,8 +55,8 @@ public class SpringApplicationAdminJmxAutoConfiguration {
5555

5656
@Bean
5757
@ConditionalOnMissingBean
58-
public SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar(
59-
ObjectProvider<MBeanExporter> mbeanExporters, Environment environment) throws MalformedObjectNameException {
58+
SpringApplicationAdminMXBeanRegistrar springApplicationAdminRegistrar(ObjectProvider<MBeanExporter> mbeanExporters,
59+
Environment environment) throws MalformedObjectNameException {
6060
String jmxName = environment.getProperty(JMX_NAME_PROPERTY, DEFAULT_JMX_NAME);
6161
if (mbeanExporters != null) { // Make sure to not register that MBean twice
6262
for (MBeanExporter mbeanExporter : mbeanExporters) {

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
*/
4646
@AutoConfiguration
4747
@ConditionalOnBooleanProperty(name = "spring.aop.auto", matchIfMissing = true)
48-
public class AopAutoConfiguration {
48+
public final class AopAutoConfiguration {
4949

5050
@Configuration(proxyBeanMethods = false)
5151
@ConditionalOnClass(Advice.class)

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/availability/ApplicationAvailabilityAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@
3131
* @since 2.3.0
3232
*/
3333
@AutoConfiguration
34-
public class ApplicationAvailabilityAutoConfiguration {
34+
public final class ApplicationAvailabilityAutoConfiguration {
3535

3636
@Bean
3737
@ConditionalOnMissingBean(ApplicationAvailability.class)
38-
public ApplicationAvailabilityBean applicationAvailability() {
38+
ApplicationAvailabilityBean applicationAvailability() {
3939
return new ApplicationAvailabilityBean();
4040
}
4141

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@
3333
*/
3434
@AutoConfiguration
3535
@EnableConfigurationProperties
36-
public class ConfigurationPropertiesAutoConfiguration {
36+
public final class ConfigurationPropertiesAutoConfiguration {
3737

3838
}

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/LifecycleAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
*/
3535
@AutoConfiguration
3636
@EnableConfigurationProperties(LifecycleProperties.class)
37-
public class LifecycleAutoConfiguration {
37+
public final class LifecycleAutoConfiguration {
3838

3939
@Bean(name = AbstractApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME)
4040
@ConditionalOnMissingBean(name = AbstractApplicationContext.LIFECYCLE_PROCESSOR_BEAN_NAME,
4141
search = SearchStrategy.CURRENT)
42-
public DefaultLifecycleProcessor defaultLifecycleProcessor(LifecycleProperties properties) {
42+
DefaultLifecycleProcessor defaultLifecycleProcessor(LifecycleProperties properties) {
4343
DefaultLifecycleProcessor lifecycleProcessor = new DefaultLifecycleProcessor();
4444
lifecycleProcessor.setTimeoutPerShutdownPhase(properties.getTimeoutPerShutdownPhase().toMillis());
4545
return lifecycleProcessor;

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@
6868
@Conditional(ResourceBundleCondition.class)
6969
@EnableConfigurationProperties(MessageSourceProperties.class)
7070
@ImportRuntimeHints(MessageSourceRuntimeHints.class)
71-
public class MessageSourceAutoConfiguration {
71+
public final class MessageSourceAutoConfiguration {
7272

7373
private static final Resource[] NO_RESOURCES = {};
7474

7575
@Bean
76-
public MessageSource messageSource(MessageSourceProperties properties) {
76+
MessageSource messageSource(MessageSourceProperties properties) {
7777
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
7878
if (!CollectionUtils.isEmpty(properties.getBasename())) {
7979
messageSource.setBasenames(properties.getBasename().toArray(new String[0]));

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@
3535
*/
3636
@AutoConfiguration
3737
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
38-
public class PropertyPlaceholderAutoConfiguration {
38+
public final class PropertyPlaceholderAutoConfiguration {
3939

4040
@Bean
4141
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
42-
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
42+
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
4343
return new PropertySourcesPlaceholderConfigurer();
4444
}
4545

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,26 @@
4949
*/
5050
@AutoConfiguration
5151
@EnableConfigurationProperties(ProjectInfoProperties.class)
52-
public class ProjectInfoAutoConfiguration {
52+
public final class ProjectInfoAutoConfiguration {
5353

5454
private final ProjectInfoProperties properties;
5555

56-
public ProjectInfoAutoConfiguration(ProjectInfoProperties properties) {
56+
ProjectInfoAutoConfiguration(ProjectInfoProperties properties) {
5757
this.properties = properties;
5858
}
5959

6060
@Conditional(GitResourceAvailableCondition.class)
6161
@ConditionalOnMissingBean
6262
@Bean
63-
public GitProperties gitProperties() throws Exception {
63+
GitProperties gitProperties() throws Exception {
6464
return new GitProperties(
6565
loadFrom(this.properties.getGit().getLocation(), "git", this.properties.getGit().getEncoding()));
6666
}
6767

6868
@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
6969
@ConditionalOnMissingBean
7070
@Bean
71-
public BuildProperties buildProperties() throws Exception {
71+
BuildProperties buildProperties() throws Exception {
7272
return new BuildProperties(
7373
loadFrom(this.properties.getBuild().getLocation(), "build", this.properties.getBuild().getEncoding()));
7474
}

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,18 @@
5353
@EnableConfigurationProperties(JmxProperties.class)
5454
@ConditionalOnClass({ MBeanExporter.class })
5555
@ConditionalOnBooleanProperty("spring.jmx.enabled")
56-
public class JmxAutoConfiguration {
56+
public final class JmxAutoConfiguration {
5757

5858
private final JmxProperties properties;
5959

60-
public JmxAutoConfiguration(JmxProperties properties) {
60+
JmxAutoConfiguration(JmxProperties properties) {
6161
this.properties = properties;
6262
}
6363

6464
@Bean
6565
@Primary
6666
@ConditionalOnMissingBean(value = MBeanExporter.class, search = SearchStrategy.CURRENT)
67-
public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy, BeanFactory beanFactory) {
67+
AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy, BeanFactory beanFactory) {
6868
AnnotationMBeanExporter exporter = new AnnotationMBeanExporter();
6969
exporter.setRegistrationPolicy(this.properties.getRegistrationPolicy());
7070
exporter.setNamingStrategy(namingStrategy);
@@ -78,7 +78,7 @@ public AnnotationMBeanExporter mbeanExporter(ObjectNamingStrategy namingStrategy
7878

7979
@Bean
8080
@ConditionalOnMissingBean(value = ObjectNamingStrategy.class, search = SearchStrategy.CURRENT)
81-
public ParentAwareNamingStrategy objectNamingStrategy() {
81+
ParentAwareNamingStrategy objectNamingStrategy() {
8282
ParentAwareNamingStrategy namingStrategy = new ParentAwareNamingStrategy(new AnnotationJmxAttributeSource());
8383
String defaultDomain = this.properties.getDefaultDomain();
8484
if (StringUtils.hasLength(defaultDomain)) {
@@ -90,7 +90,7 @@ public ParentAwareNamingStrategy objectNamingStrategy() {
9090

9191
@Bean
9292
@ConditionalOnMissingBean
93-
public MBeanServer mbeanServer() {
93+
MBeanServer mbeanServer() {
9494
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
9595
factory.setLocateExistingServerIfPossible(true);
9696
factory.afterPropertiesSet();

0 commit comments

Comments
 (0)