エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

【恥晒し】SpringBootのアップデートで依存関係の循環に対処した

経緯

SpringBoot2.6→3.0にバージョンアップした際に、依存関係が循環しているみたいなメッセージがでてきた。具体的な内容は、下記の通り

The dependencies of some of the beans in the application context form a cycle:

   minhonController (field private com.galewings.service.MinhonService com.galewings.controller.MinhonController.service)
┌─────┐
|  minhonService (field okhttp3.OkHttpClient com.galewings.service.MinhonService.okHttpClient)
└─────┘

発生していた例外(一部抜粋)

2023/07/05 08:59:07 DEBUG [restartedMain] - Application failed to start due to an exception
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'minhonService': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:412)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1324)

//・・・・

実装内容

原因となる実装

原因となっていた箇所のソース

@Service
@Component
public class MinhonService {

// ・・・・

    @Autowired
    OkHttpClient client;

    @Autowired
    private RestTemplate restTemplate;


    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient();
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

// ・・・・
}

おそらく、okHttpClientのインスタンスがほしいけど、MinhonServiceのインスタンスを生成する必要がある。MinhonServiceのインスタンスを生成しようとしたら、okHttpClientのインスタンスを設定する必要がある。以下、ループ。

本来は、分けているのがSpringFWの思想的に正しそうな気がするが、実装するときにクラス作るのが面倒で、同じクラスに書いたら、この問題を踏んだ。。。

解消方法

生成と利用箇所を分けるように実装した。
具体的には、以下の通り

@Service
@Component
public class MinhonService {

// ・・・・

    @Autowired
    OkHttpClient client;

    @Autowired
    private RestTemplate restTemplate;

// ・・・・
}
@Configuration
public class MinhonBeanConfig {

    @Bean
    public OkHttpClient okHttpClient() {
        return new OkHttpClient();
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

たぶん、本来あるべき姿はこうなのだろう。
なぜ、一緒にしていても動いていたのかは不明。。。
あきらかに沼りそうだから、調べたくはないってのが本音。