回答編集履歴

2

追記

2020/06/07 12:35

投稿

rubytomato
rubytomato

スコア1752

test CHANGED
@@ -305,3 +305,219 @@
305
305
  };
306
306
 
307
307
  ```
308
+
309
+
310
+
311
+ **2020/06/07 追記**
312
+
313
+
314
+
315
+ > 「Quote quote = restTemplate.getForObject(」こちらの行から読み取れるに、「Quote」型の変数を返しているということではないのでしょうか...?
316
+
317
+
318
+
319
+ すでに回答に記載していますが`CommandLineRunner`インターフェースのrunメソッドのシグネチャは以下の通りです。
320
+
321
+ このように戻り値の型がvoidとなっているのでrunメソッドは何も返しません。`args`という文字列の配列を引数に取り(それを使うかどうかは別として)実装した処理を実行する(Springフレームワークが)だけです。
322
+
323
+
324
+
325
+ ```java
326
+
327
+ void run(String... args) throws Exception;
328
+
329
+ ```
330
+
331
+
332
+
333
+ なので
334
+
335
+
336
+
337
+ > 「Quote」型の変数を返している
338
+
339
+
340
+
341
+ ということではありません。
342
+
343
+
344
+
345
+ 以下が参考にされているページのオリジナルコードですが、このrunメソッド内でreturnしているのはラムダ式で書かれた`CommandLineRunner`インターフェースを実装したクラス(匿名クラス、無名クラスとも)のインスタンスです。
346
+
347
+
348
+
349
+ ```java
350
+
351
+ @Bean
352
+
353
+ public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
354
+
355
+
356
+
357
+ return args -> {
358
+
359
+ Quote quote = restTemplate.getForObject(
360
+
361
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
362
+
363
+ log.info(quote.toString());
364
+
365
+ };
366
+
367
+
368
+
369
+ }
370
+
371
+ ```
372
+
373
+
374
+
375
+ 上記の書き方を少し冗長化すると下記のようになります。returnは`CommandLineRunner`型の変数runnerを返していることが分かりやすくなったかとおもいます。
376
+
377
+ ラムダ式について少し触れておくと、`args -> { ... }`は、`args`がメソッドの引数で、`-> { ... }`がメソッドの本体ということになります。
378
+
379
+
380
+
381
+ ```java
382
+
383
+ @Bean
384
+
385
+ public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
386
+
387
+
388
+
389
+ CommandLineRunner runner;
390
+
391
+
392
+
393
+ runner = args -> {
394
+
395
+ Quote quote = restTemplate.getForObject(
396
+
397
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
398
+
399
+ log.info(quote.toString());
400
+
401
+ };
402
+
403
+
404
+
405
+ return runner;
406
+
407
+ }
408
+
409
+ ```
410
+
411
+
412
+
413
+ 上記の書き方をラムダ式を使わずに記述すると下記のようになります。
414
+
415
+ これはいわゆるラムダ式導入以前の匿名クラス(無名クラス)を利用している書き方です。runner変数には匿名クラスのインスタンスが代入され、それがreturnされています。
416
+
417
+ さらにオーバーライドしたrunメソッドが何もreturnしていないことがわかると思います。
418
+
419
+
420
+
421
+ ```java
422
+
423
+ @Bean
424
+
425
+ public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
426
+
427
+
428
+
429
+ CommandLineRunner runner = new CommandLineRunner() {
430
+
431
+ @Override
432
+
433
+ public void run(String... args) throws Exception {
434
+
435
+ Quote quote = restTemplate.getForObject(
436
+
437
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
438
+
439
+ log.info(quote.toString());
440
+
441
+ }
442
+
443
+ };
444
+
445
+
446
+
447
+ return runner;
448
+
449
+ }
450
+
451
+ ```
452
+
453
+
454
+
455
+ 上記の書き方は匿名クラスを使った例ですが、下記のように書くこともできます。
456
+
457
+
458
+
459
+ ```java
460
+
461
+ public class CustomRunner implements CommandLineRunner {
462
+
463
+ private static final Logger log = LoggerFactory.getLogger(CustomRunner.class);
464
+
465
+
466
+
467
+ private final RestTemplate restTemplate;
468
+
469
+
470
+
471
+ public CustomRunner(RestTemplate restTemplate) {
472
+
473
+ this.restTemplate = restTemplate;
474
+
475
+ }
476
+
477
+
478
+
479
+ @Override
480
+
481
+ public void run(String... args) throws Exception {
482
+
483
+ Quote quote = restTemplate.getForObject(
484
+
485
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
486
+
487
+ log.info(quote.toString());
488
+
489
+ }
490
+
491
+
492
+
493
+ }
494
+
495
+ ```
496
+
497
+
498
+
499
+ これで`CommandLineRunner`インターフェースを実装したクラスのインスタンスを返していることがわかるでしょうか?
500
+
501
+
502
+
503
+ ```java
504
+
505
+ @Bean
506
+
507
+ public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
508
+
509
+
510
+
511
+ CommandLineRunner runner = new CustomRunner(restTemplate);
512
+
513
+
514
+
515
+ return runner;
516
+
517
+ }
518
+
519
+ ```
520
+
521
+
522
+
523
+ すでに説明したと思いますが、returnしたインスタンスのrunメソッドは、アプリケーション起動時にSpringフレームワークによって実行されます。

1

追記

2020/06/07 12:35

投稿

rubytomato
rubytomato

スコア1752

test CHANGED
@@ -123,3 +123,185 @@
123
123
  };
124
124
 
125
125
  ```
126
+
127
+
128
+
129
+ **2020/06/06 追記**
130
+
131
+
132
+
133
+ > 一点のみどうしても疑問があるのですが、元コードの「run」メソッドの引数「args」はメソッド内で一度も使用されていないにも関わらず、記載されているのは何故
134
+
135
+
136
+
137
+ 元コードというのは下記のことだと思いますが、端的に言うと引数`args`が記載されているのは`CommandLineRunner`インターフェースを実装しているからであり、引数を使用していないのはサンプルコード上必要がなかったから、ということではないでしょうか?
138
+
139
+
140
+
141
+ ```java
142
+
143
+ return args -> {
144
+
145
+ Quote quote = restTemplate.getForObject(
146
+
147
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
148
+
149
+ log.info(quote.toString());
150
+
151
+ };
152
+
153
+ ```
154
+
155
+
156
+
157
+ 以下は`CommandLineRunner`インターフェースのコードです。このインターフェースを実装するということは`void run(String... args) throws Exception`をオーバーライドする必要があるということです。
158
+
159
+
160
+
161
+ ```java
162
+
163
+ @FunctionalInterface
164
+
165
+ public interface CommandLineRunner {
166
+
167
+
168
+
169
+ /**
170
+
171
+ * Callback used to run the bean.
172
+
173
+ * @param args incoming main method arguments
174
+
175
+ * @throws Exception on error
176
+
177
+ */
178
+
179
+ void run(String... args) throws Exception;
180
+
181
+
182
+
183
+ }
184
+
185
+ ```
186
+
187
+
188
+
189
+ このインターフェースを実装したクラスのコードは例えば以下のようになります。このようにrunメソッドをオーバーライドして、Springアプリケーションの起動時に実行したい処理を記述します。
190
+
191
+
192
+
193
+ ```java
194
+
195
+ @Component
196
+
197
+ public class CustomRunner implements CommandLineRunner {
198
+
199
+ private static final Logger log = LoggerFactory.getLogger(CustomRunner.class);
200
+
201
+
202
+
203
+ private final RestTemplate restTemplate;
204
+
205
+
206
+
207
+ public CustomRunner(RestTemplate restTemplate) {
208
+
209
+ this.restTemplate = restTemplate;
210
+
211
+ }
212
+
213
+
214
+
215
+ @Override
216
+
217
+ public void run(String... args) throws Exception {
218
+
219
+ log.info(Arrays.toString(args));
220
+
221
+ Quote quote = restTemplate.getForObject(
222
+
223
+ "https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
224
+
225
+ log.info("2nd : {}", quote.toString());
226
+
227
+ }
228
+
229
+
230
+
231
+ }
232
+
233
+ ```
234
+
235
+
236
+
237
+ runメソッドの引数を使う必要がないからといって以下のようにオーバーライドしてもコンパイルエラーになります。なぜならこれでは`CommandLineRunner`インターフェースを実装していることにならないからです。
238
+
239
+
240
+
241
+ ```java
242
+
243
+ @Override
244
+
245
+ public void run() throws Exception {
246
+
247
+
248
+
249
+ // 省略
250
+
251
+
252
+
253
+ }
254
+
255
+ ```
256
+
257
+
258
+
259
+ ちなみに、引数を使うように実装するのであれば、以下のようにすることもできます。
260
+
261
+
262
+
263
+ サンプルコードで使用しているAPIの`https://gturnquist-quoters.cfapps.io/api/random`は、randomの部分を任意の数値に変えると、それがID指定になります。
264
+
265
+ たとえば、`https://gturnquist-quoters.cfapps.io/api/10`でリクエストすると、以下のjsonがレスポンスされます。
266
+
267
+
268
+
269
+ ```json
270
+
271
+ {
272
+
273
+ "type":"success",
274
+
275
+ "value":{
276
+
277
+ "id":10,
278
+
279
+ "quote":"Really loving Spring Boot, makes stand alone Spring apps easy."
280
+
281
+ }
282
+
283
+ }
284
+
285
+ ```
286
+
287
+
288
+
289
+ このように実装すると(引数のチェックをしていないので例は悪いですが)、アプリケーション実行時の引数にIDを指定することができるようになります。
290
+
291
+
292
+
293
+ ```java
294
+
295
+ return args -> {
296
+
297
+ String id = args[0];
298
+
299
+ Quote quote = restTemplate.getForObject(
300
+
301
+ "https://gturnquist-quoters.cfapps.io/api/" + id, Quote.class);
302
+
303
+ log.info(quote.toString());
304
+
305
+ };
306
+
307
+ ```