Skip to content

Commit 2072e72

Browse files
committed
Merge branch '2.3.x' into 2.4.x
Closes gh-24841
2 parents 5d85ac6 + 283ed48 commit 2072e72

File tree

6 files changed

+71
-29
lines changed

6 files changed

+71
-29
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
2424

2525
import javax.sql.DataSource;
2626

27+
import com.zaxxer.hikari.HikariConfigMXBean;
2728
import com.zaxxer.hikari.HikariDataSource;
2829
import com.zaxxer.hikari.metrics.micrometer.MicrometerMetricsTrackerFactory;
2930
import io.micrometer.core.instrument.MeterRegistry;
@@ -112,7 +113,8 @@ static class HikariDataSourceMetricsConfiguration {
112113
@Autowired
113114
void bindMetricsRegistryToHikariDataSources(Collection<DataSource> dataSources) {
114115
for (DataSource dataSource : dataSources) {
115-
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class);
116+
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariConfigMXBean.class,
117+
HikariDataSource.class);
116118
if (hikariDataSource != null) {
117119
bindMetricsRegistryToHikariDataSource(hikariDataSource);
118120
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,10 +20,12 @@
2020

2121
import javax.sql.DataSource;
2222

23+
import com.zaxxer.hikari.HikariConfigMXBean;
2324
import com.zaxxer.hikari.HikariDataSource;
2425
import org.apache.commons.logging.Log;
2526
import org.apache.commons.logging.LogFactory;
2627
import org.apache.tomcat.jdbc.pool.DataSourceProxy;
28+
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
2729

2830
import org.springframework.beans.factory.ObjectProvider;
2931
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -62,7 +64,8 @@ static class Hikari {
6264
}
6365

6466
private void validateMBeans() {
65-
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(this.dataSource, HikariDataSource.class);
67+
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(this.dataSource, HikariConfigMXBean.class,
68+
HikariDataSource.class);
6669
if (hikariDataSource != null && hikariDataSource.isRegisterMbeans()) {
6770
this.mBeanExporter.ifUnique((exporter) -> exporter.addExcludedBean("dataSource"));
6871
}
@@ -79,7 +82,8 @@ static class TomcatDataSourceJmxConfiguration {
7982
@Bean
8083
@ConditionalOnMissingBean(name = "dataSourceMBean")
8184
Object dataSourceMBean(DataSource dataSource) {
82-
DataSourceProxy dataSourceProxy = DataSourceUnwrapper.unwrap(dataSource, DataSourceProxy.class);
85+
DataSourceProxy dataSourceProxy = DataSourceUnwrapper.unwrap(dataSource, PoolConfiguration.class,
86+
DataSourceProxy.class);
8387
if (dataSourceProxy != null) {
8488
try {
8589
return dataSourceProxy.createPool().getJmxPool();

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,10 +16,13 @@
1616

1717
package org.springframework.boot.autoconfigure.jdbc.metadata;
1818

19+
import com.zaxxer.hikari.HikariConfigMXBean;
1920
import com.zaxxer.hikari.HikariDataSource;
2021
import oracle.jdbc.OracleConnection;
2122
import oracle.ucp.jdbc.PoolDataSource;
2223
import org.apache.commons.dbcp2.BasicDataSource;
24+
import org.apache.commons.dbcp2.BasicDataSourceMXBean;
25+
import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;
2326

2427
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2528
import org.springframework.boot.jdbc.DataSourceUnwrapper;
@@ -50,7 +53,7 @@ static class TomcatDataSourcePoolMetadataProviderConfiguration {
5053
DataSourcePoolMetadataProvider tomcatPoolDataSourceMetadataProvider() {
5154
return (dataSource) -> {
5255
org.apache.tomcat.jdbc.pool.DataSource tomcatDataSource = DataSourceUnwrapper.unwrap(dataSource,
53-
org.apache.tomcat.jdbc.pool.DataSource.class);
56+
ConnectionPoolMBean.class, org.apache.tomcat.jdbc.pool.DataSource.class);
5457
if (tomcatDataSource != null) {
5558
return new TomcatDataSourcePoolMetadata(tomcatDataSource);
5659
}
@@ -67,7 +70,8 @@ static class HikariPoolDataSourceMetadataProviderConfiguration {
6770
@Bean
6871
DataSourcePoolMetadataProvider hikariPoolDataSourceMetadataProvider() {
6972
return (dataSource) -> {
70-
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class);
73+
HikariDataSource hikariDataSource = DataSourceUnwrapper.unwrap(dataSource, HikariConfigMXBean.class,
74+
HikariDataSource.class);
7175
if (hikariDataSource != null) {
7276
return new HikariDataSourcePoolMetadata(hikariDataSource);
7377
}
@@ -84,7 +88,8 @@ static class CommonsDbcp2PoolDataSourceMetadataProviderConfiguration {
8488
@Bean
8589
DataSourcePoolMetadataProvider commonsDbcp2PoolDataSourceMetadataProvider() {
8690
return (dataSource) -> {
87-
BasicDataSource dbcpDataSource = DataSourceUnwrapper.unwrap(dataSource, BasicDataSource.class);
91+
BasicDataSource dbcpDataSource = DataSourceUnwrapper.unwrap(dataSource, BasicDataSourceMXBean.class,
92+
BasicDataSource.class);
8893
if (dbcpDataSource != null) {
8994
return new CommonsDbcp2DataSourcePoolMetadata(dbcpDataSource);
9095
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceUnwrapper.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,35 +43,52 @@ private DataSourceUnwrapper() {
4343

4444
/**
4545
* Return an object that implements the given {@code target} type, unwrapping delegate
46-
* or proxy if necessary.
46+
* or proxy if necessary using the specified {@code unwrapInterface}.
4747
* @param dataSource the datasource to handle
48+
* @param unwrapInterface the interface that the target type must implement
4849
* @param target the type that the result must implement
50+
* @param <I> the interface that the target type must implement
4951
* @param <T> the target type
5052
* @return an object that implements the target type or {@code null}
53+
* @see Wrapper#unwrap(Class)
5154
*/
52-
public static <T> T unwrap(DataSource dataSource, Class<T> target) {
55+
public static <I, T extends I> T unwrap(DataSource dataSource, Class<I> unwrapInterface, Class<T> target) {
5356
if (target.isInstance(dataSource)) {
5457
return target.cast(dataSource);
5558
}
56-
T unwrapped = safeUnwrap(dataSource, target);
57-
if (unwrapped != null) {
58-
return unwrapped;
59+
I unwrapped = safeUnwrap(dataSource, unwrapInterface);
60+
if (unwrapped != null && unwrapInterface.isAssignableFrom(target)) {
61+
return target.cast(unwrapped);
5962
}
6063
if (DELEGATING_DATA_SOURCE_PRESENT) {
6164
DataSource targetDataSource = DelegatingDataSourceUnwrapper.getTargetDataSource(dataSource);
6265
if (targetDataSource != null) {
63-
return unwrap(targetDataSource, target);
66+
return unwrap(targetDataSource, unwrapInterface, target);
6467
}
6568
}
6669
if (AopUtils.isAopProxy(dataSource)) {
6770
Object proxyTarget = AopProxyUtils.getSingletonTarget(dataSource);
6871
if (proxyTarget instanceof DataSource) {
69-
return unwrap((DataSource) proxyTarget, target);
72+
return unwrap((DataSource) proxyTarget, unwrapInterface, target);
7073
}
7174
}
7275
return null;
7376
}
7477

78+
/**
79+
* Return an object that implements the given {@code target} type, unwrapping delegate
80+
* or proxy if necessary. Consider using {@link #unwrap(DataSource, Class, Class)} as
81+
* {@link Wrapper#unwrap(Class) unwrapping} won't be considered if {@code target} is
82+
* not an interface.
83+
* @param dataSource the datasource to handle
84+
* @param target the type that the result must implement
85+
* @param <T> the target type
86+
* @return an object that implements the target type or {@code null}
87+
*/
88+
public static <T> T unwrap(DataSource dataSource, Class<T> target) {
89+
return unwrap(dataSource, target, target);
90+
}
91+
7592
private static <S> S safeUnwrap(Wrapper wrapper, Class<S> target) {
7693
try {
7794
if (target.isInterface() && wrapper.isWrapperFor(target)) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceUnwrapperNoSpringJdbcTests.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,8 +18,10 @@
1818

1919
import javax.sql.DataSource;
2020

21+
import com.zaxxer.hikari.HikariConfigMXBean;
2122
import com.zaxxer.hikari.HikariDataSource;
2223
import org.apache.tomcat.jdbc.pool.DataSourceProxy;
24+
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
2325
import org.junit.jupiter.api.Test;
2426

2527
import org.springframework.aop.framework.ProxyFactory;
@@ -39,14 +41,16 @@ class DataSourceUnwrapperNoSpringJdbcTests {
3941
void unwrapWithProxy() {
4042
DataSource dataSource = new HikariDataSource();
4143
DataSource actual = wrapInProxy(wrapInProxy(dataSource));
42-
assertThat(DataSourceUnwrapper.unwrap(actual, HikariDataSource.class)).isSameAs(dataSource);
44+
assertThat(DataSourceUnwrapper.unwrap(actual, HikariConfigMXBean.class, HikariDataSource.class))
45+
.isSameAs(dataSource);
4346
}
4447

4548
@Test
4649
void unwrapDataSourceProxy() {
4750
org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
4851
DataSource actual = wrapInProxy(wrapInProxy(dataSource));
49-
assertThat(DataSourceUnwrapper.unwrap(actual, DataSourceProxy.class)).isSameAs(dataSource);
52+
assertThat(DataSourceUnwrapper.unwrap(actual, PoolConfiguration.class, DataSourceProxy.class))
53+
.isSameAs(dataSource);
5054
}
5155

5256
private DataSource wrapInProxy(DataSource dataSource) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceUnwrapperTests.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,13 +21,16 @@
2121

2222
import javax.sql.DataSource;
2323

24+
import com.zaxxer.hikari.HikariConfigMXBean;
2425
import com.zaxxer.hikari.HikariDataSource;
2526
import org.apache.tomcat.jdbc.pool.DataSourceProxy;
27+
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
2628
import org.junit.jupiter.api.Test;
2729

2830
import org.springframework.aop.framework.ProxyFactory;
2931
import org.springframework.jdbc.datasource.DelegatingDataSource;
3032
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
33+
import org.springframework.jdbc.datasource.SmartDataSource;
3134

3235
import static org.assertj.core.api.Assertions.assertThat;
3336
import static org.mockito.Mockito.mock;
@@ -44,52 +47,59 @@ class DataSourceUnwrapperTests {
4447
@Test
4548
void unwrapWithTarget() {
4649
DataSource dataSource = new HikariDataSource();
47-
assertThat(DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class)).isSameAs(dataSource);
50+
assertThat(DataSourceUnwrapper.unwrap(dataSource, HikariConfigMXBean.class, HikariDataSource.class))
51+
.isSameAs(dataSource);
4852
}
4953

5054
@Test
5155
void unwrapWithWrongTarget() {
5256
DataSource dataSource = new HikariDataSource();
53-
assertThat(DataSourceUnwrapper.unwrap(dataSource, SingleConnectionDataSource.class)).isNull();
57+
assertThat(DataSourceUnwrapper.unwrap(dataSource, SmartDataSource.class, SingleConnectionDataSource.class))
58+
.isNull();
5459
}
5560

5661
@Test
5762
void unwrapWithDelegate() {
5863
DataSource dataSource = new HikariDataSource();
5964
DataSource actual = wrapInDelegate(wrapInDelegate(dataSource));
60-
assertThat(DataSourceUnwrapper.unwrap(actual, HikariDataSource.class)).isSameAs(dataSource);
65+
assertThat(DataSourceUnwrapper.unwrap(actual, HikariConfigMXBean.class, HikariDataSource.class))
66+
.isSameAs(dataSource);
6167
}
6268

6369
@Test
6470
void unwrapWithProxy() {
6571
DataSource dataSource = new HikariDataSource();
6672
DataSource actual = wrapInProxy(wrapInProxy(dataSource));
67-
assertThat(DataSourceUnwrapper.unwrap(actual, HikariDataSource.class)).isSameAs(dataSource);
73+
assertThat(DataSourceUnwrapper.unwrap(actual, HikariConfigMXBean.class, HikariDataSource.class))
74+
.isSameAs(dataSource);
6875
}
6976

7077
@Test
7178
void unwrapWithProxyAndDelegate() {
7279
DataSource dataSource = new HikariDataSource();
7380
DataSource actual = wrapInProxy(wrapInDelegate(dataSource));
74-
assertThat(DataSourceUnwrapper.unwrap(actual, HikariDataSource.class)).isSameAs(dataSource);
81+
assertThat(DataSourceUnwrapper.unwrap(actual, HikariConfigMXBean.class, HikariDataSource.class))
82+
.isSameAs(dataSource);
7583
}
7684

7785
@Test
7886
void unwrapWithSeveralLevelOfWrapping() {
7987
DataSource dataSource = new HikariDataSource();
8088
DataSource actual = wrapInProxy(wrapInDelegate(wrapInDelegate(wrapInProxy(wrapInDelegate(dataSource)))));
81-
assertThat(DataSourceUnwrapper.unwrap(actual, HikariDataSource.class)).isSameAs(dataSource);
89+
assertThat(DataSourceUnwrapper.unwrap(actual, HikariConfigMXBean.class, HikariDataSource.class))
90+
.isSameAs(dataSource);
8291
}
8392

8493
@Test
8594
void unwrapDataSourceProxy() {
8695
org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
8796
DataSource actual = wrapInDelegate(wrapInProxy(dataSource));
88-
assertThat(DataSourceUnwrapper.unwrap(actual, DataSourceProxy.class)).isSameAs(dataSource);
97+
assertThat(DataSourceUnwrapper.unwrap(actual, PoolConfiguration.class, DataSourceProxy.class))
98+
.isSameAs(dataSource);
8999
}
90100

91101
@Test
92-
void unwrappingIsNotAttemptedWhenTargetIsNotAnInterface() throws SQLException {
102+
void unwrappingIsNotAttemptedWhenTargetIsNotAnInterface() {
93103
DataSource dataSource = mock(DataSource.class);
94104
assertThat(DataSourceUnwrapper.unwrap(dataSource, HikariDataSource.class)).isNull();
95105
verifyNoMoreInteractions(dataSource);

0 commit comments

Comments
 (0)