簡體   English   中英

Spring Boot 中的循環依賴

[英]Cyclic dependency in Spring Boot

將 org.springframework.boot 從 2.5.6 版本升級到 2.6.2 版本后,應用程序啟動時出現以下錯誤:

***************************
APPLICATION FAILED TO START
***************************

Description:

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

┌─────┐
|  securityConfiguration
↑     ↓
|  org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
└─────┘

我從其他問題中知道,簡單的解決方法是使用選項allow-cirular-references ,但我想真正解決問題而不是使用解決方法。

這是我的安全配置 class:

package com.mycompany.myapp.servicex.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${application.myapp.in-browser-allowed-origins}")
    private String[] inBrowserAllowedOrigins;

    private final String[] inBrowserAllowedMethods = new String[]{"POST", "OPTIONS"};

    @Override
    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();
    }

    @Bean
    public WebMvcConfigurer corsConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/in-browser/login")
                        .allowedOrigins(inBrowserAllowedOrigins)
                        .allowedMethods(inBrowserAllowedMethods);
                registry.addMapping("/**").allowedOrigins();
            }
        };
    }
}


有人知道如何以編程方式打破循環依賴嗎?

我已經在corsConfigurer bean 和inBrowserAllowedOrigins屬性中使用 @Lazy 注釋,但沒有成功。

不要為WebMvcConfigurer使用內部 bean,而是將其設置為正確的 class ,您可以使用@Configuration對其進行注釋。

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Value("${application.myapp.in-browser-allowed-origins}")
    private String[] inBrowserAllowedOrigins;

    private final String[] inBrowserAllowedMethods = new String[]{"POST", "OPTIONS"};

 @Override
 public void addCorsMappings(CorsRegistry registry) {
   registry.addMapping("/in-browser/login")
     .allowedOrigins(inBrowserAllowedOrigins)
     .allowedMethods(inBrowserAllowedMethods);
   registry.addMapping("/**").allowedOrigins();
  }
}

現在您可以從您的安全配置中刪除corsConfiguration() @Bean方法,循環依賴就消失了。

或者另一種選擇是使用 Spring Security 來配置 CORS 而不是 Spring MVC。 這在Spring 安全參考指南中進行了解釋。

為此,您需要修改安全配置

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Value("${application.myapp.in-browser-allowed-origins}")
    private String[] inBrowserAllowedOrigins;

    private final String[] inBrowserAllowedMethods = new String[]{"POST", "OPTIONS"};

    @Override
    protected void configure(final HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable()
                .cors(withDefaults());
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
      CorsConfiguration conf = new CorsConfiguration();      
      conf.setAllowedOrigins(Arrays.asList(inBrowserAllowedOrigins));       
      conf.setAllowedMethods(Arrays.asList(inBrowserAllowedMethods));
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/in-browser/login", configuration);
        source.registerCorsConfiguration("/**", new CorsConfiguration());
        return source;       
    }
}

這樣的事情也應該有效,因為現在 Spring 安全性已完全控制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM