我正在使用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,UserDetailsService和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;
}
的UserDetailsService
@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之间发生了变化。与此有关[如果有一个适合这个问题的简单描述]。
答案 0 :(得分:2)
正如消息所说,应用程序中的四个bean之间存在循环依赖关系。更详细的说,这个周期是:
PeopleController
取决于LrqaPersonService
LrqaPersonService
取决于由PasswordEncoder
SecurityConfig
SecurityConfig
取决于PersonDetailsService
PersonDetailsService
取决于LrqaPersonService
你需要以某种方式打破这个循环。
查看代码,不清楚为什么PasswordEncoder
被注入LrqaPersonService
,因为它似乎未被使用。最简单的解决方法可能是从PasswordEncoder
删除LrqaPersonService
。
如果由于某种原因你不能这样做,我认为你可以通过将@Bean
的{{1}}方法从PasswordEncoder
移到单独的{{1}来打破周期} class。