Spring Boot 1.4.0循环依赖异常

时间:2016-08-17 10:59:33

标签: spring spring-boot

我正在使用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;
          }

的UserDetailsS​​ervice

@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之间发生了变化。与此有关[如果有一个适合这个问题的简单描述]。

1 个答案:

答案 0 :(得分:2)

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

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

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

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

如果由于某种原因你不能这样做,我认为你可以通过将@Bean的{​​{1}}方法从PasswordEncoder移到单独的{{1}来打破周期} class。