【问题标题】:Spring Boot 1.4.0 Circular Dependency ExceptionSpring Boot 1.4.0 循环依赖异常
【发布时间】:2016-08-17 10:59:33
【问题描述】:

我正在使用 Spring Boot 1.4.0,并且在编译代码时遇到循环依赖异常。我的项目结构是标准的,并且结构相同的项目使用 Spring Boot 1.3.5 运行良好。我希望找到一种方法来消除循环依赖异常。

项目 Gradle 文件

dependencies {
  compile('org.springframework.boot:spring-boot-starter-security')
  compile('org.springframework.boot:spring-boot-starter-web')
  compile('org.springframework.boot:spring-boot-starter-data-mongodb')
  compile('org.springframework.boot:spring-boot-starter-data-rest')
  compile('org.springframework.boot:spring-boot-starter-actuator')
  compile('org.springframework.hateoas:spring-hateoas')
  testCompile('org.springframework.boot:spring-boot-starter-test')
}

我的项目结构遵循标准的 MVC 模式,从下到上依次为 MongoDB、Repository、Service、Controller、UserDetailsS​​ervice 和 Spring Security Configuration。

如下:

存储库

@Repository
public interface LrqaPersonRepository extends MongoRepository<LrqaPerson,       String> {

  public LrqaPerson findByEmail(String email);
  public List<LrqaPerson> findByCountry(String country);

}

服务

 @Autowired
      public LrqaPersonService(LrqaPersonRepository lrqaPersonRepository,
                             PasswordEncoder encoder){

        this.lrqaPersonRepository = lrqaPersonRepository;
        this.encoder = encoder;
        }   


        public LrqaPerson findSingleLrqaPerson(String id){
              logger.info("LrqaPersonService method findSingleLrqaPerson() invoked: " + LocalDateTime.now());
              LrqaPerson lrqaPerson = this.lrqaPersonRepository.findOne(id);
              return lrqaPerson;
          }

用户详细信息服务

@Service("personDetailsService")
public class PersonDetailsService implements UserDetailsService {

private static final Logger logger =     LoggerFactory.getLogger(PersonDetailsService.class);

private List<GrantedAuthority> auth;

@Autowired
LrqaPersonService personService;

@Override
public UserDetails loadUserByUsername(String email)
        throws UsernameNotFoundException {

    logger.info("LrqaPersonDetailsService loadUserByUsername() invoked: " + LocalDateTime.now());
    LrqaPerson person = personService.findLrqaPersonByEmail(email);

    if (person == null) {
        throw new UsernameNotFoundException("Invalid Email Username");
    }

    if (person.getAuthority().equals("user")) {
        logger.info("LrqaPersonDetailsService authority privilege detected: " + person.getAuthority());
        auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
    }

    if (person.getAuthority().equals("admin")) {
        logger.info("LrqaPersonDetailsService authority privilege detected: " + person.getAuthority());
        auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN, ROLE_USER");
    }

    return new org.springframework.security.core.userdetails.User(
            email, person.getPassword(), auth);

}
}

控制器

@RestController
public class PeopleController {


private final LrqaPersonService personService;
private static final Logger logger =   LoggerFactory.getLogger(PeopleController.class);

@Autowired
public PeopleController(LrqaPersonService personService){
    this.personService = personService;
}

@RequestMapping(value = "/allpeople", method = RequestMethod.GET)
public List<LrqaPerson> getAllLrqaPeople(){
    logger.info("LrqaGenericController method getAllLrqaPeople() invoked: " + LocalDateTime.now());
    List<LrqaPerson> lrqaPeople = this.personService.findAllLrqaPersons();
    return lrqaPeople;
}

我在运行 ./gradlew bootRun --debug 时遇到的异常是:

例外

11:12:36.141 [QUIET] [system.out] ***************************
11:12:36.141 [QUIET] [system.out] APPLICATION FAILED TO START
11:12:36.141 [QUIET] [system.out] ***************************
11:12:36.141 [QUIET] [system.out] 
11:12:36.141 [QUIET] [system.out] Description:
11:12:36.142 [QUIET] [system.out] 
11:12:36.142 [QUIET] [system.out] There is a circular dependency between 4   beans in the application context:
11:12:36.142 [QUIET] [system.out]   - peopleController defined in file   [/Users/frank***/Development/IntelliJ/springAngularJSTutorial/build/classes/main  /org/frank/***/controller/PeopleController.class]
11:12:36.142 [QUIET] [system.out]   - lrqaPersonService defined in file [/Users/frank***/Development/IntelliJ/springAngularJSTutorial/build/classes/main/org/frank/***/service/LrqaPersonService.class]
11:12:36.142 [QUIET] [system.out]   - securityConfig
11:12:36.142 [QUIET] [system.out]   - personDetailsService (field org.frank.***.service.LrqaPersonService org.frank.***.security.PersonDetailsService.personService)
11:12:36.142 [QUIET] [system.out]   - lrqaPersonService
11:12:36.142 [QUIET] [system.out] 
11:12:36.142 [QUIET] [system.out] 
11:12:36.180 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: FAILED

我的安全配置如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Resource(name = "personDetailsService")
private PersonDetailsService personDetailsService;

@Autowired
public void configureAuth(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.inMemoryAuthentication()
            .withUser("****").password("****").roles("USER");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/user", "/index.html", "/home.html", "/login.html", "/").permitAll()
            .anyRequest().authenticated().and()
            .formLogin().and()
            .httpBasic().and()
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    ;
}
@Bean
public PasswordEncoder passwordEncoder() {
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    return encoder;
}
@Override
protected void configure(AuthenticationManagerBuilder builder) throws     Exception {              builder.userDetailsService(personDetailsService).passwordEncoder(passwordEncoder());
}
}

我注意到各种在线论坛上对该问题的一些报道。如果有一个循环依赖异常的解决方案,并且我可以在任何地方找到关于为什么 Boot 1.3.5 应用程序结构不生成异常的解释,这对我来说将是一个很大的帮助。也就是说,在 1.3.5 和 1.4.0 之间发生了什么变化。关于这个[如果有适合这个问题的简单描述]。

【问题讨论】:

    标签: spring spring-boot


    【解决方案1】:

    正如消息中所说,您的应用程序中的四个 bean 之间存在循环依赖关系。更详细地说,这个循环是:

    • PeopleController 取决于 LrqaPersonService
    • LrqaPersonService 依赖于由 SecurityConfig 生成的 PasswordEncoder
    • SecurityConfig 取决于 PersonDetailsService
    • PersonDetailsService 取决于 LrqaPersonService

    你需要以某种方式打破这个循环。

    查看代码,不清楚为什么PasswordEncoder 被注入LrqaPersonService,因为它似乎没有被使用。最简单的解决方法可能是从LrqaPersonService 中删除PasswordEncoder

    如果由于某种原因你不能这样做,我认为你可以通过将 PasswordEncoder@Bean 方法从 SecurityConfig 移动到单独的 @Configuration 类来打破循环。

    【讨论】:

      猜你喜欢
      • 2020-07-15
      • 2015-05-17
      • 2016-12-21
      • 2022-01-18
      • 2020-09-25
      • 2018-09-29
      • 2018-09-21
      • 1970-01-01
      • 2020-02-18
      相关资源
      最近更新 更多