Autowire doesn't work for custom UserDetailsService in Spring Boot

会有一股神秘感。 提交于 2019-12-11 03:38:35

问题


The spring boot apps starts up, tomcat runs, and then it throws an error before finally dying.

Error

Running my app gives me this Autowired error:

2016-07-29 02:18:24.737 ERROR 44715 --- [  restartedMain] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myapp.MyUserDetailsService myapp.WebSecurityConfig.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [myapp.MyUserDetailsService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.7.RELEASE.jar:4.2.7.RELEASE]

Details

My Security configuration:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
        .antMatchers("/", "/register").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/")
        .permitAll()
        .and()
        .logout()
        .permitAll();
}

@Autowired
private MyUserDetailsService userDetailsService;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
}

}

MyUserDetails:

@Service
@Transactional
public class MyUserDetailsService implements UserDetailsService {

@Autowired
private UserRepository userRepository;


public MyUserDetailsService() {
        super();
}

@Override
public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException {
        User user = userRepository.findByUserName(userName);
        if (user == null) {
                return null;
        }
        List<GrantedAuthority> auth = AuthorityUtils
                                      .commaSeparatedStringToAuthorityList("ROLE_USER");
        String password = user.getPassword();
        return new org.springframework.security.core.userdetails.User(userName, password,
                                                                      auth);
}



}

You may find full source code at Git Repo


回答1:


I've tried your project at commit 3b9a6a2e, and the error is actually different:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private myapp.MyUserDetailsService myapp.WebSecurityConfig.userDetailsService; nested exception is java.lang.IllegalArgumentException: Can not set myapp.MyUserDetailsService field myapp.WebSecurityConfig.userDetailsService to com.sun.proxy.$Proxy80

Which makes your question a duplicate of Spring can't create beans. Solution: replace

@Autowired
private MyUserDetailsService userDetailsService;

with

@Autowired
private UserDetailsService userDetailsService;

Your solution (removing @Transactional) works because without @Transactional there is no reason for Spring to wrap MyUserDetailsService in a proxy.




回答2:


Removing @Transactional from MyUserDetailsService worked. No idea why. If someone has an explanation, please post and it i'll mark it as the answer.

Double checked, this really is correct, if you'd like to check for yourself, please check out commit 840f0753bdca1592d9070c74bc87f30e8e2f87a7 for the repository listed above, and test it.

And stop downvoting this answer because you think it's incorrect.




回答3:


Add @ComponentScan to WebSecurityConfig.

This should wire in MyUserDetailsService due to component scanning as it is annotated with @Service.

A package name can be passed as a parameter to the annotation to set the scope of component scanning, for example:

@ComponentScan("com.company.team")



回答4:


please add Annotation: @ComponentScan("") on main configuration class.

If you want to create bean/service for specific directory then you can give package path inside @ComponentScan("package.to.scan")



来源:https://stackoverflow.com/questions/38647002/autowire-doesnt-work-for-custom-userdetailsservice-in-spring-boot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!