31
31
import org .apache .tomcat .jdbc .pool .jmx .ConnectionPool ;
32
32
import org .junit .Test ;
33
33
34
+ import org .springframework .aop .framework .AopProxyUtils ;
34
35
import org .springframework .aop .framework .ProxyFactory ;
36
+ import org .springframework .aop .support .AopUtils ;
35
37
import org .springframework .beans .factory .config .BeanPostProcessor ;
36
38
import org .springframework .boot .autoconfigure .AutoConfigurations ;
37
39
import org .springframework .boot .autoconfigure .jmx .JmxAutoConfiguration ;
38
40
import org .springframework .boot .test .context .runner .ApplicationContextRunner ;
39
41
import org .springframework .context .annotation .Bean ;
40
42
import org .springframework .context .annotation .Configuration ;
43
+ import org .springframework .jdbc .datasource .DelegatingDataSource ;
41
44
42
45
import static org .assertj .core .api .Assertions .assertThat ;
43
46
44
47
/**
45
48
* Tests for {@link DataSourceJmxConfiguration}.
46
49
*
47
50
* @author Stephane Nicoll
51
+ * @author Tadaya Tsuyukubo
48
52
*/
49
53
public class DataSourceJmxConfigurationTests {
50
54
@@ -162,6 +166,78 @@ public void tomcatAutoConfiguredCanExposeMBeanPool() {
162
166
});
163
167
}
164
168
169
+ @ Test
170
+ public void tomcatProxiedCanExposeMBeanPool () {
171
+ this .contextRunner .withUserConfiguration (DataSourceProxyConfiguration .class )
172
+ .withPropertyValues (
173
+ "spring.datasource.type=" + DataSource .class .getName (),
174
+ "spring.datasource.jmx-enabled=true" )
175
+ .run ((context ) -> {
176
+ assertThat (context ).hasSingleBean (ConnectionPool .class );
177
+ DataSourceProxy dataSourceProxy = (DataSourceProxy ) AopProxyUtils
178
+ .getSingletonTarget (
179
+ context .getBean (javax .sql .DataSource .class ));
180
+ assertThat (dataSourceProxy .createPool ().getJmxPool ())
181
+ .isSameAs (context .getBean (ConnectionPool .class ));
182
+ });
183
+ }
184
+
185
+ @ Test
186
+ public void tomcatDelegateCanExposeMBeanPool () {
187
+ this .contextRunner .withUserConfiguration (DataSourceDelegateConfiguration .class )
188
+ .withPropertyValues (
189
+ "spring.datasource.type=" + DataSource .class .getName (),
190
+ "spring.datasource.jmx-enabled=true" )
191
+ .run ((context ) -> {
192
+ assertThat (context ).hasSingleBean (ConnectionPool .class );
193
+ DataSourceProxy dataSourceProxy = (DataSourceProxy ) context
194
+ .getBean (DelegatingDataSource .class ).getTargetDataSource ();
195
+ assertThat (dataSourceProxy .createPool ().getJmxPool ())
196
+ .isSameAs (context .getBean (ConnectionPool .class ));
197
+ });
198
+ }
199
+
200
+ @ Test
201
+ public void tomcatProxyAndDelegateCanExposeMBeanPool () {
202
+ this .contextRunner
203
+ .withUserConfiguration (DataSourceMixWrapAndProxyConfiguration .class )
204
+ .withPropertyValues (
205
+ "spring.datasource.type=" + DataSource .class .getName (),
206
+ "spring.datasource.jmx-enabled=true" )
207
+ .run ((context ) -> {
208
+ assertThat (context ).hasSingleBean (ConnectionPool .class );
209
+ DataSourceProxy dataSourceProxy = extractTomcatDataSource (
210
+ context .getBean (javax .sql .DataSource .class ));
211
+ assertThat (dataSourceProxy .createPool ().getJmxPool ())
212
+ .isSameAs (context .getBean (ConnectionPool .class ));
213
+ });
214
+ }
215
+
216
+ private static javax .sql .DataSource wrap (javax .sql .DataSource dataSource ) {
217
+ return (javax .sql .DataSource ) new ProxyFactory (dataSource ).getProxy ();
218
+ }
219
+
220
+ private static javax .sql .DataSource delegate (javax .sql .DataSource dataSource ) {
221
+ return new DelegatingDataSource (dataSource );
222
+ }
223
+
224
+ private static DataSource extractTomcatDataSource (javax .sql .DataSource dataSource ) {
225
+ if (dataSource instanceof DataSource ) {
226
+ return (DataSource ) dataSource ;
227
+ }
228
+ else if (dataSource instanceof DelegatingDataSource ) {
229
+ return extractTomcatDataSource (
230
+ ((DelegatingDataSource ) dataSource ).getTargetDataSource ());
231
+ }
232
+ else if (AopUtils .isAopProxy (dataSource )) {
233
+ return extractTomcatDataSource (
234
+ (javax .sql .DataSource ) AopProxyUtils .getSingletonTarget (dataSource ));
235
+ }
236
+
237
+ throw new RuntimeException (
238
+ "Not proxied or delegated tomcat DataSource: " + dataSource );
239
+ }
240
+
165
241
@ Configuration
166
242
static class DataSourceProxyConfiguration {
167
243
@@ -182,8 +258,53 @@ public Object postProcessAfterInitialization(Object bean, String beanName) {
182
258
return bean ;
183
259
}
184
260
185
- private static javax .sql .DataSource wrap (javax .sql .DataSource dataSource ) {
186
- return (javax .sql .DataSource ) new ProxyFactory (dataSource ).getProxy ();
261
+ }
262
+
263
+ @ Configuration
264
+ static class DataSourceDelegateConfiguration {
265
+
266
+ @ Bean
267
+ public static DataSourceBeanPostProcessor dataSourceBeanPostProcessor () {
268
+ return new DataSourceBeanPostProcessor () {
269
+ @ Override
270
+ public Object postProcessAfterInitialization (Object bean ,
271
+ String beanName ) {
272
+ if (bean instanceof javax .sql .DataSource ) {
273
+ return new DelegatingDataSource ((javax .sql .DataSource ) bean );
274
+ }
275
+ return bean ;
276
+ }
277
+ };
278
+ }
279
+
280
+ }
281
+
282
+ @ Configuration
283
+ static class DataSourceMixWrapAndProxyConfiguration {
284
+
285
+ @ Bean
286
+ public static DataSourceBeanPostProcessor dataSourceBeanPostProcessor () {
287
+ return new DataSourceBeanPostProcessor () {
288
+ @ Override
289
+ public Object postProcessAfterInitialization (Object bean ,
290
+ String beanName ) {
291
+ if (bean instanceof javax .sql .DataSource ) {
292
+ javax .sql .DataSource dataSource = (javax .sql .DataSource ) bean ;
293
+ // delegate/wrap multiple times
294
+ for (int i = 0 ; i < 10 ; i ++) {
295
+ if (i % 2 == 0 ) {
296
+ dataSource = wrap (dataSource );
297
+ }
298
+ else {
299
+ dataSource = delegate (dataSource );
300
+ }
301
+ }
302
+
303
+ return dataSource ;
304
+ }
305
+ return bean ;
306
+ }
307
+ };
187
308
}
188
309
189
310
}
0 commit comments