简体   繁体   中英

Spring circular references prohibited in 2.6 version

I have an issue for circular reference calling. Even if I set true to this option, I cannot fix my issue. How can I fix it? Here are my code snippets which are shown below step by step.

Here is my application.properties file shown below.

...
spring.main.allow-circular-references= true
...

Here is my error message shown below.

Description:

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

   userController (field com.photoapp.users.service.UserService com.photoapp.users.controller.UserController.userService)
┌─────┐
|  userServiceImpl defined in file [C:\Users\de\Desktop\sts-4.9.0.RELEASE\workspace\PhotoAppApiUsers\target\classes\com\photoapp\users\service\impl\UserServiceImpl.class]
↑     ↓
|  webSecurity defined in file [C:\Users\de\Desktop\sts-4.9.0.RELEASE\workspace\PhotoAppApiUsers\target\classes\com\photoapp\users\security\WebSecurity.class]
└─────┘


Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

Here is my userServiceImpl class

@Service
@Transactional
public class UserServiceImpl implements UserService{

    UserMapper userMapper;
    
    UserRepository userRepository;
    
    PasswordEncoder passwordEncoder;
    
    @Autowired
    public UserServiceImpl(UserMapper userMapper,UserRepository userRepository,PasswordEncoder passwordEncoder) {
        super();
        this.userMapper = userMapper;
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }


    @Override
    public UserDto createUser(UserDto userDetails) {
        // TODO Auto-generated method stub
        
        userDetails.setUserId(UUID.randomUUID().toString());
        
        User user = userMapper.userDtotoUser(userDetails);
        
        
        String encodedPassword = passwordEncoder.encode(userDetails.getPassword());
        user.setEncryptedPassword(encodedPassword);
        
        userRepository.save(user);
        
        UserDto returnValue = userMapper.userToUserDto(user);
 
        return returnValue;
        
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // TODO Auto-generated method stub
        User user = userRepository.findByEmail(username);
        
        if(user == null) 
            throw new UsernameNotFoundException(username);  
        
        return new org.springframework.security.core.userdetails.User(user.getEmail(), 
                user.getEncryptedPassword(), 
                true, true, true, true, new ArrayList<>());
    }
    
    @Override
    public UserDto getUserDetailsByEmail(String email) { 
        User user = userRepository.findByEmail(email);
        
        if(user == null) 
            throw new UsernameNotFoundException(email);
        
        UserDto returnValue = userMapper.userToUserDto(user);
        
        return returnValue;
    }


    @Override
    public UserDto getUserByUserId(String userId) {
        // TODO Auto-generated method stub
        return null;
    }

}

Here is my WebSecurity class

@Configuration
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {

    
    private Environment environment;
    private UserService userService;
    
    @Autowired
    public WebSecurity(Environment environment, UserService userService) {
        super();
        this.environment = environment;
        this.userService = userService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // TODO Auto-generated method stub
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/users").hasIpAddress(environment.getProperty("gateway.ip"))
        .and()
        .addFilter(getAuthenticationFilter());
        http.headers().frameOptions().disable();
    }

    private AuthenticationFilter getAuthenticationFilter() throws Exception{
        AuthenticationFilter authenticationFilter = new AuthenticationFilter(userService, environment, authenticationManager());
        //authenticationFilter.setAuthenticationManager(authenticationManager()); 
        authenticationFilter.setFilterProcessesUrl(environment.getProperty("login.url.path"));
        return authenticationFilter;
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
}

Here is my solution

public UserServiceImpl(UserMapper userMapper,UserRepository userRepository,@Lazy PasswordEncoder passwordEncoder) {
        super();
        this.userMapper = userMapper;
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

Try using @Lazy

public class WebSecurity extends WebSecurityConfigurerAdapter {

    
    private Environment environment;
    @Lazy
    private UserService userService;

Reference: https://www.baeldung.com/spring-lazy-annotation

The error message is pretty clear. UserServiceImpl depends on WebSecurity which depends on UserServiceImpl .

The dependency from WebSecurity to UserServiceImpl is necessary. That means you need to break the dependency from UserServiceImpl to WebSecurity . This is caused by the password encoder. You need to move that out of WebSecurity . Maybe you can integrate it in UserServiceImpl ?

If you declare the bean factory method for the password encoder static , ie

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

you make it clear that the bean does not actually depend on anything that is injected into WebSecurity . Then, you don't need to work with @Lazy and the proxying it creates.

You may even be able to remove the property that allows circular references. But that depends on the whole rest of your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM