Skip to content

Commit 560315a

Browse files
committed
GH-315 - Avoid processing infrastructure beans in observability infrastructure.
We now skip infrastructure role beans during the processing of beans that could be subject to inter-module interaction observability. Previously, we could accidentally trigger a dependency cycle if the ModuleTracingBeanPostProcessor triggered the initial creation of AutoConfigurationPackages as that would then trigger the PostProcessor in turn which would try to lookup the ACP bean again to determine whether it should post process that to apply observability.
1 parent cc99f9d commit 560315a

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

spring-modulith-observability/src/main/java/org/springframework/modulith/observability/ModuleTracingBeanPostProcessor.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
import org.springframework.aop.support.DefaultPointcutAdvisor;
2828
import org.springframework.aop.support.StaticMethodMatcher;
2929
import org.springframework.beans.BeansException;
30+
import org.springframework.beans.factory.config.BeanDefinition;
3031
import org.springframework.beans.factory.config.BeanPostProcessor;
31-
import org.springframework.modulith.core.ApplicationModules;
32+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3233
import org.springframework.modulith.runtime.ApplicationModulesRuntime;
3334
import org.springframework.util.Assert;
3435

@@ -45,6 +46,7 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
4546
private final ApplicationModulesRuntime runtime;
4647
private final Supplier<Tracer> tracer;
4748
private final Map<String, Advisor> advisors;
49+
private final ConfigurableListableBeanFactory factory;
4850

4951
/**
5052
* Creates a new {@link ModuleTracingBeanPostProcessor} for the given {@link ApplicationModulesRuntime} and
@@ -53,14 +55,16 @@ public class ModuleTracingBeanPostProcessor extends ModuleTracingSupport impleme
5355
* @param runtime must not be {@literal null}.
5456
* @param tracer must not be {@literal null}.
5557
*/
56-
public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<Tracer> tracer) {
58+
public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplier<Tracer> tracer,
59+
ConfigurableListableBeanFactory factory) {
5760

5861
Assert.notNull(runtime, "ApplicationModulesRuntime must not be null!");
5962
Assert.notNull(tracer, "Tracer must not be null!");
6063

6164
this.runtime = runtime;
6265
this.tracer = tracer;
6366
this.advisors = new HashMap<>();
67+
this.factory = factory;
6468
}
6569

6670
/*
@@ -70,13 +74,13 @@ public ModuleTracingBeanPostProcessor(ApplicationModulesRuntime runtime, Supplie
7074
@Override
7175
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
7276

73-
Class<?> type = runtime.getUserClass(bean, beanName);
77+
var type = runtime.getUserClass(bean, beanName);
7478

75-
if (!runtime.isApplicationClass(type) || !type.isInstance(bean)) {
79+
if (!type.isInstance(bean) || isInfrastructureBean(beanName) || !runtime.isApplicationClass(type)) {
7680
return bean;
7781
}
7882

79-
ApplicationModules modules = runtime.get();
83+
var modules = runtime.get();
8084

8185
return modules.getModuleByType(type.getName())
8286
.map(DefaultObservedModule::new)
@@ -91,6 +95,12 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
9195
}).orElse(bean);
9296
}
9397

98+
private boolean isInfrastructureBean(String beanName) {
99+
100+
return factory.containsBean(beanName) &&
101+
factory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE;
102+
}
103+
94104
private Advisor getOrBuildAdvisor(ObservedModule module, ObservedModuleType type) {
95105

96106
return advisors.computeIfAbsent(module.getName(), __ -> {

spring-modulith-observability/src/main/java/org/springframework/modulith/observability/autoconfigure/ModuleObservabilityAutoConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import io.micrometer.tracing.Tracer;
2626

2727
import org.springframework.beans.factory.ObjectProvider;
28+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
2829
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2930
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3031
import org.springframework.context.annotation.Bean;
@@ -42,8 +43,8 @@ class ModuleObservabilityAutoConfiguration {
4243

4344
@Bean
4445
static ModuleTracingBeanPostProcessor moduleTracingBeanPostProcessor(ApplicationModulesRuntime runtime,
45-
ObjectProvider<Tracer> tracer) {
46-
return new ModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject());
46+
ObjectProvider<Tracer> tracer, ConfigurableListableBeanFactory factory) {
47+
return new ModuleTracingBeanPostProcessor(runtime, () -> tracer.getObject(), factory);
4748
}
4849

4950
@Bean

spring-modulith-runtime/src/main/java/org/springframework/modulith/runtime/autoconfigure/SpringBootApplicationRuntime.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.springframework.modulith.runtime.autoconfigure;
1717

1818
import java.util.Arrays;
19+
import java.util.List;
1920
import java.util.Map;
2021
import java.util.concurrent.ConcurrentHashMap;
2122

@@ -38,6 +39,7 @@ class SpringBootApplicationRuntime implements ApplicationRuntime {
3839

3940
private final ApplicationContext context;
4041
private Class<?> mainApplicationClass;
42+
private List<String> resolvedAutoConfigurationPackages;
4143

4244
/**
4345
* Creates a new {@link SpringBootApplicationRuntime} for the given {@link ApplicationContext}.
@@ -113,6 +115,15 @@ private boolean computeIsApplicationClass(String fqn, Class<?> applicationClass)
113115
}
114116

115117
return fqn.startsWith(applicationClass.getPackage().getName())
116-
|| AutoConfigurationPackages.get(context).stream().anyMatch(pkg -> fqn.startsWith(pkg));
118+
|| getAutoConfigurationPackages().stream().anyMatch(pkg -> fqn.startsWith(pkg));
119+
}
120+
121+
private List<String> getAutoConfigurationPackages() {
122+
123+
if (resolvedAutoConfigurationPackages == null) {
124+
this.resolvedAutoConfigurationPackages = AutoConfigurationPackages.get(context);
125+
}
126+
127+
return resolvedAutoConfigurationPackages;
117128
}
118129
}

0 commit comments

Comments
 (0)