Skip to content

Commit ed68a10

Browse files
Merge branch '2.2.x'
2 parents 9d11503 + aea67cb commit ed68a10

File tree

3 files changed

+92
-11
lines changed

3 files changed

+92
-11
lines changed

spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ else if (bean instanceof Executor) {
120120

121121
private Object wrapExecutor(Object bean) {
122122
Executor executor = (Executor) bean;
123-
boolean methodFinal = anyFinalMethods(executor, Executor.class);
123+
boolean methodFinal = anyFinalMethods(executor);
124124
boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers());
125125
boolean cglibProxy = !methodFinal && !classFinal;
126126
try {
@@ -144,31 +144,31 @@ private Object wrapExecutor(Object bean) {
144144
private Object wrapThreadPoolTaskExecutor(Object bean) {
145145
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean;
146146
boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers());
147-
boolean methodsFinal = anyFinalMethods(executor, ThreadPoolTaskExecutor.class);
147+
boolean methodsFinal = anyFinalMethods(executor);
148148
boolean cglibProxy = !classFinal && !methodsFinal;
149149
return createThreadPoolTaskExecutorProxy(bean, cglibProxy, executor);
150150
}
151151

152152
private Object wrapExecutorService(Object bean) {
153153
ExecutorService executor = (ExecutorService) bean;
154154
boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers());
155-
boolean methodFinal = anyFinalMethods(executor, ExecutorService.class);
155+
boolean methodFinal = anyFinalMethods(executor);
156156
boolean cglibProxy = !classFinal && !methodFinal;
157157
return createExecutorServiceProxy(bean, cglibProxy, executor);
158158
}
159159

160160
private Object wrapScheduledExecutorService(Object bean) {
161161
ScheduledExecutorService executor = (ScheduledExecutorService) bean;
162162
boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers());
163-
boolean methodFinal = anyFinalMethods(executor, ExecutorService.class);
163+
boolean methodFinal = anyFinalMethods(executor);
164164
boolean cglibProxy = !classFinal && !methodFinal;
165165
return createScheduledExecutorServiceProxy(bean, cglibProxy, executor);
166166
}
167167

168168
private Object wrapAsyncTaskExecutor(Object bean) {
169169
AsyncTaskExecutor executor = (AsyncTaskExecutor) bean;
170170
boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers());
171-
boolean methodsFinal = anyFinalMethods(executor, AsyncTaskExecutor.class);
171+
boolean methodsFinal = anyFinalMethods(executor);
172172
boolean cglibProxy = !classFinal && !methodsFinal;
173173
return createAsyncTaskExecutorProxy(bean, cglibProxy, executor);
174174
}
@@ -304,12 +304,17 @@ private SleuthAsyncProperties asyncConfigurationProperties() {
304304
return this.sleuthAsyncProperties;
305305
}
306306

307-
private static <T> boolean anyFinalMethods(T object, Class<T> iface) {
307+
private static <T> boolean anyFinalMethods(T object) {
308308
try {
309-
for (Method method : ReflectionUtils.getDeclaredMethods(iface)) {
309+
for (Method method : ReflectionUtils
310+
.getAllDeclaredMethods(object.getClass())) {
311+
if (method.getDeclaringClass().equals(Object.class)) {
312+
continue;
313+
}
310314
Method m = ReflectionUtils.findMethod(object.getClass(), method.getName(),
311315
method.getParameterTypes());
312-
if (m != null && Modifier.isFinal(m.getModifiers())) {
316+
if (m != null && Modifier.isPublic(m.getModifiers())
317+
&& Modifier.isFinal(m.getModifiers())) {
313318
return true;
314319
}
315320
}

spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
import java.util.concurrent.Future;
2828
import java.util.concurrent.RejectedExecutionException;
2929
import java.util.concurrent.ScheduledExecutorService;
30+
import java.util.concurrent.ScheduledThreadPoolExecutor;
3031
import java.util.concurrent.TimeUnit;
3132
import java.util.concurrent.TimeoutException;
3233
import java.util.concurrent.atomic.AtomicBoolean;
3334

3435
import brave.Tracing;
3536
import org.aopalliance.aop.Advice;
3637
import org.assertj.core.api.BDDAssertions;
38+
import org.awaitility.Awaitility;
3739
import org.junit.jupiter.api.AfterEach;
3840
import org.junit.jupiter.api.BeforeEach;
3941
import org.junit.jupiter.api.Test;
@@ -340,6 +342,21 @@ public void should_use_jdk_proxy_when_executor_has_final_methods() {
340342
then(wasCalled).isTrue();
341343
}
342344

345+
@Test
346+
public void should_use_cglib_proxy_when_an_executor_has_a_final_package_protected_method() {
347+
ExecutorBeanPostProcessor beanPostProcessor = new ExecutorBeanPostProcessor(
348+
this.beanFactory);
349+
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
350+
ScheduledThreadPoolExecutor wrappedExecutor = (ScheduledThreadPoolExecutor) beanPostProcessor
351+
.postProcessAfterInitialization(executor, "executor");
352+
353+
then(AopUtils.isCglibProxy(wrappedExecutor)).isTrue();
354+
355+
AtomicBoolean wasCalled = new AtomicBoolean(false);
356+
wrappedExecutor.execute(() -> wasCalled.set(true));
357+
Awaitility.await().untilAsserted(() -> then(wasCalled).isTrue());
358+
}
359+
343360
@Test
344361
public void should_use_jdk_proxy_when_executor_service_has_final_methods()
345362
throws Exception {
@@ -459,6 +476,44 @@ public void should_not_double_instrument_traced_executors() throws Exception {
459476

460477
}
461478

479+
// #1569
480+
@Test
481+
public void should_use_jdk_proxy_when_executor_has_any_final_methods() {
482+
ExecutorBeanPostProcessor beanPostProcessor = new ExecutorBeanPostProcessor(
483+
this.beanFactory);
484+
485+
Executor wrappedExecutor = (Executor) beanPostProcessor
486+
.postProcessAfterInitialization(new ExecutorWithFinalMethod(),
487+
"executorWithFinalMethod");
488+
489+
then(AopUtils.isJdkDynamicProxy(wrappedExecutor)).isTrue();
490+
then(AopUtils.isCglibProxy(wrappedExecutor)).isFalse();
491+
AtomicBoolean wasCalled = new AtomicBoolean(false);
492+
wrappedExecutor.execute(() -> {
493+
wasCalled.set(true);
494+
});
495+
then(wasCalled).isTrue();
496+
}
497+
498+
// #1569
499+
@Test
500+
public void should_use_jdk_proxy_when_executor_has_an_inherited_final_methods() {
501+
ExecutorBeanPostProcessor beanPostProcessor = new ExecutorBeanPostProcessor(
502+
this.beanFactory);
503+
504+
Executor wrappedExecutor = (Executor) beanPostProcessor
505+
.postProcessAfterInitialization(new ExecutorWithInheritedFinalMethod(),
506+
"executorWithFinalMethod");
507+
508+
then(AopUtils.isJdkDynamicProxy(wrappedExecutor)).isTrue();
509+
then(AopUtils.isCglibProxy(wrappedExecutor)).isFalse();
510+
AtomicBoolean wasCalled = new AtomicBoolean(false);
511+
wrappedExecutor.execute(() -> {
512+
wasCalled.set(true);
513+
});
514+
then(wasCalled).isTrue();
515+
}
516+
462517
class Foo implements Executor {
463518

464519
@Override
@@ -504,4 +559,27 @@ public final void execute(Runnable task, long startTimeout) {
504559

505560
}
506561

562+
static class ExecutorWithFinalMethod implements Executor {
563+
564+
@Override
565+
public void execute(Runnable command) {
566+
command.run();
567+
}
568+
569+
public final void foo() {
570+
571+
}
572+
573+
}
574+
575+
static class ExecutorWithInheritedFinalMethod extends ExecutorWithFinalMethod
576+
implements Executor {
577+
578+
@Override
579+
public void execute(Runnable command) {
580+
command.run();
581+
}
582+
583+
}
584+
507585
}

tests/spring-cloud-sleuth-instrumentation-async-tests/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.cloud.sleuth.instrument.async.issues.issue410;
1818

19-
import java.lang.invoke.MethodHandles;
2019
import java.util.Date;
2120
import java.util.concurrent.CompletableFuture;
2221
import java.util.concurrent.ExecutionException;
@@ -62,8 +61,7 @@
6261
webEnvironment = WebEnvironment.RANDOM_PORT)
6362
public class Issue410Tests {
6463

65-
private static final Log log = LogFactory
66-
.getLog(MethodHandles.lookup().lookupClass());
64+
private static final Log log = LogFactory.getLog(Issue410Tests.class);
6765

6866
@Autowired
6967
Environment environment;

0 commit comments

Comments
 (0)