创建多个bean时出错:是否存在无法解析的循环引用?

8xiog9wr  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(405)

当我尝试实现登录api的一部分并尝试运行它时,我遇到了许多错误,如以下错误:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-02-12 02:23:23.314 ERROR 25840 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\controllers\UserController.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\security\config\WebSecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\services\UserService.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1206) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.3.jar:5.3.3]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\security\config\WebSecurityConfig.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\services\UserService.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.3.jar:5.3.3]
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService' defined in file [C:\Users\chafy\Desktop\cub\back\target\classes\com\cesi\cuberil\services\UserService.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.3.jar:5.3.3]
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227) ~[spring-beans-5.3.3.jar:5.3.3]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.3.jar:5.3.3]

我对spring se还不熟悉,我不知道这个错误是什么意思。
这里有以下几类:
用户控制器:

@RestController
@RequestMapping(path="api/v1/user")
@AllArgsConstructor
@CrossOrigin(origins = "*")
public class UserController implements Routes {

    private final AuthenticationManager authenticationManager;
    private final RegistrationService registrationService;

    @PostMapping(registration)
    public String register(@RequestBody RegistrationRequest request){
        return registrationService.register(request);
    }

    @PostMapping(login)
    public ResponseEntity<?> login(@Valid @RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUserName(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);
        User myUserDetails = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> roles = myUserDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());

        return ResponseEntity.ok("OKKKK CONNECté");
    }

    @PostMapping(resetPassword)
    public String resetPassword() {
        return "Password reset";
    }

    @GetMapping(path = confirm)
    public String confirm(@RequestParam("token") String token) {
        return registrationService.confirmToken(token);
    }
}

用户服务:

@Service
@AllArgsConstructor
public class UserService implements UserDetailsService {

    private final static String USER_NOT_FOUND_MESSAGE = "user with email %s not found";
    private final UserRepository userRepository;
    private final ConfirmationTokenService confirmationTokenService;
    private final AuthenticationManager authenticationManager;

    @Override
    public UserDetails loadUserByUsername(String email)
            throws UsernameNotFoundException {
        return userRepository.findByEmail(email)
                .orElseThrow(() -> new UsernameNotFoundException(String.format(USER_NOT_FOUND_MESSAGE, email)));
    }

    public String signUpUser(User user) {
        boolean userExists = userRepository.findByEmail(user.getEmail()).isPresent();
        if (userExists) {
            throw new IllegalStateException("Email already taken");
        }
        String encodedPassword = bCryptPasswordEncoder().encode(user.getPassword());
        user.setPassword(encodedPassword);
        userRepository.save(user);
        String token = UUID.randomUUID().toString();
        //TODO: Send Confirmation Token
        ConfirmationToken confirmationToken = new ConfirmationToken(
                token,
                LocalDateTime.now(),
                LocalDateTime.now().plusMinutes(15),
                user
        );

        confirmationTokenService.saveConfirmationToken(confirmationToken);

        //TODO: SEND EMAIL

        return "Token: " + token + "\nFirstname: " + user.getFirstName() + "\nLastname: " + user.getLastName() +
                "\nUsername: " + user.getUsername() + "\nEmail: " + user.getEmail();
    }

    public int enableAppUser(String email) {
        return userRepository.enableAppUser(email);
    }

    public AuthenticationResponse login(LoginRequest loginRequest) {
        Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUserName(),
                loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        return new AuthenticationResponse(loginRequest.getUserName());
    }

    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

Web安全配置:

@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserService userService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests().antMatchers("/api/v*/**").permitAll()
                .anyRequest()
                .authenticated().and()
                .formLogin();

    }
@Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userService)
                .passwordEncoder(passwordEncoder());
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

我不明白的意思:有一个无法解决的循环引用?我把所有的都拿走了 @Autowired 注解,因为spring将尝试查找匹配类型的bean。我知道那是问题所在,但不是。

fnx2tebb

fnx2tebb1#

spring使用反反转控制原理,这意味着您不必创建对象,您可以通过依赖注入来添加它们。
当您通过lombok的@allargsconstuctor构造函数在websecurityconfig中注入依赖项时,您告诉spring注入那些bean。在那个阶段,它没有userservicebean所需的bean“authenticationmanager”。
解决方案是使用autowired通过方法的参数注入userservice

@Override
@Autowired
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder, UserService userService) throws Exception {
    authenticationManagerBuilder.userDetailsService(userService)
            .passwordEncoder(passwordEncoder());
}

并删除类字段userservice。

走错了路

@SpringBootApplication
public class DemoApplication {

    UserService userService;

    public DemoApplication(UserService userService) {
        this.userService = userService;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    public TestService testService() {
        return new TestService();
    }
}

日志

Description:

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

┌─────┐
|  demoApplication
↑     ↓
|  userService defined in file [...\target\classes\com\example\demo\UserService.class]
└─────┘

解决方案

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Autowired
    public void userService(UserService userService) {
        System.out.println("UserService Injected: " + userService);
    }

    @Bean
    public TestService testService() {
        return new TestService();
    }
}
@Service
public class UserService {

    public UserService(TestService testService) {
        System.out.println("User Service created using: " + testService);
    }
}
public class TestService {
    public TestService() {
        System.out.println("TestService created");
    }

    @Override
    public String toString() {
        return "Test Service";
    }
}

日志

TestService created
User Service created using: Test Service
UserService Injected: com.example.demo.UserService@29629fbb

相关问题