きり丸アドベントカレンダー2020の24記事目です。
23日目の記事にて、RestOperationsインターフェースを使用して別システムのAPIを実行できるようにしました。23日目の状態では他システムのAPIを実行する直前にてインスタンスを生成していましたが、別の箇所でも使えるように生成ロジック自体を共通的にできそうです。
また、各外部連携用のクライアントで生成せずに、すでに生成された状態でインジェクションできると生成ロジックが流出しないし、記載量も減るのでいいことづくめです。
ただし、AシステムとBシステムのDI対象のRestOperations
インターフェースは同じものの、使用するコンポーネント側でURL等の各システムで特化している情報をもった異なる別のインスタンスをインジェクションさせる必要があります。
特に何の設定も行わないと、どちらのRestOperations
をインジェクションするべきかがわからないので、次のエラーログが出て起動できません。
Parameter 1 of constructor in com.example.demo.external.zipCloud.ZipCloudClientImpl required a single bean, but 2 were found: - dummyUserRestOperations: defined by method 'dummyUserRestOperations' in class path resource [com/example/demo/external/operation/RestOperationConfig.class] - zipCloudRestOperations: defined by method 'zipCloudRestOperations' in class path resource [com/example/demo/external/operation/RestOperationConfig.class]
今回の記事では、共通化して同クラスになったものの、目的別のインスタンスを使用するクラスで目的通りにインジェクションさせるようにします。
ゴール
23日目の記事では、住所コードから住所を取得するAPIを使用しました。
今回の記事では、ダミーユーザを生成してくれるAPIを使用します。
環境
手順
RestOperations生成ロジックを共通化する
23日目の記事では、生成したロジックを別クラスに移しているだけです。
解説等は上の記事から見てください。
ファイル名:RestOperationFactory.java
@RequiredArgsConstructor @Component public class RestOperationFactory { private final RestTemplateBuilder restTemplateBuilder; public RestOperations createRestOperations(ExternalProperties props) { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(List.of(MediaType.TEXT_PLAIN)); RestTemplate build = restTemplateBuilder .setConnectTimeout(Duration.ofSeconds(props.getConnectionTimeout())) .setReadTimeout(Duration.ofSeconds(props.getReadTimeout())) .build(); build.getMessageConverters().add(converter); return build; } }
システムごとのRestOperationsインスタンスを生成する
クラスに@Configuration
アノテーションを付与します。
メソッドごとに@Bean
をつけると、メソッドごとにインジェクション対象のインスタンスになります。@Bean
に何も指定しないと、メソッド名がそのまま識別名になります。
ファイル名:RestOperationConfig.java
@Configuration @RequiredArgsConstructor public class RestOperationConfig { private final RestOperationFactory restOperationFactory; @Bean RestOperations dummyUserRestOperations(DummyUserClientProperties props){ return restOperationFactory.createRestOperations(props); } @Bean RestOperations zipCloudRestOperations(ZipCloudClientProperties props){ return restOperationFactory.createRestOperations(props); } }
インスタンスを識別しながらQualifierを使用してインジェクションする
インジェクションする際に@Qualifier
を指定します。上でも説明しましたが、@Bean
のパラメータを指定していればその値を、指定しなければメソッド名を入力してください。
ファイル名:ZipCloudClientImpl.java
public ZipCloudClientImpl( ZipCloudClientProperties props, @Qualifier("zipCloudRestOperations") RestOperations restOperations ) { this.props = props; this.restOperations = restOperations; }
ソースコード
アドベントカレンダー24日目。
github.com
終わりに
やり方がわからないと、共通化に苦労してしまいます。または、生成ロジックだけは共通化したものの、各クラスでインスタンスを何度も生成する必要があります。
私はBean
とQualifier
の理解に苦しみました。
インジェクション対象で同クラス別インスタンスを扱うことはユースケースとしては少ないですが、覚えておくと地味に助かると思いますので、ぜひ覚えて下さい。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。
参考記事
敬称略
paiza開発日誌:面倒な手続き不要!「Web API」の超お手軽活用術をJavaScriptコード付きで一挙大公開! paiza.hatenablog.com
この記事に対して反応してくださった内容の方が正直濃いです。
私のブログで見たうえで、さらに良い設計をする場合はこちらの記事を参考にしてください。
blog.ik.amちょっと古い記事ですが、https://t.co/LygPHqpbcl
— Toshiaki Maki (@making) 2020年12月24日
がこちら参考になると思います
類似記事
きり丸アドベントカレンダー2020 adventar.org
きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/
25日目のアドベントカレンダーの記事。この記事は振り返りです。 https://nainaistar.hatenablog.com/entry/2020/12/25/083000nainaistar.hatenablog.com