【问题标题】:Autowire doesn't work for custom UserDetailsService in Spring BootAutowire 不适用于 Spring Boot 中的自定义 UserDetailsS​​ervice
【发布时间】:2016-07-28 21:24:07
【问题描述】:

spring boot 应用程序启动,tomcat 运行,然后在最终死机之前抛出错误。

错误

运行我的应用程序给了我这个Autowired 错误:

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]

详情

我的安全配置:

@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);
}

}

我的用户详情:

@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);
}



}

你可以在Git Repo找到完整的源代码

【问题讨论】:

  • 我喜欢通过 Git Repo url 共享代码库的想法。如果 SO 在发布问题时提供了一个可选的 Git Repo,那就太好了,这样有助于通过查看完整源代码更好地回答问题

标签: java spring spring-boot spring-ioc


【解决方案1】:

我已经在提交3b9a6a2e 尝试过你的项目,但错误实际上是不同的:

org.springframework.beans.factory.BeanCreationException:创建名为“webSecurityConfig”的bean时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 myapp.MyUserDetailsS​​ervice myapp.WebSecurityConfig.userDetailsS​​ervice;嵌套异常是 java.lang.IllegalArgumentException: 无法将 myapp.MyUserDetailsS​​ervice 字段 myapp.WebSecurityConfig.userDetailsS​​ervice 设置为 com.sun.proxy.$Proxy80

这使您的问题与Spring can't create beans 重复。解决办法:更换

@Autowired
private MyUserDetailsService userDetailsService;

@Autowired
private UserDetailsService userDetailsService;

您的解决方案(删除@Transactional)有效,因为没有@Transactional,Spring 没有理由将MyUserDetailsService 包装在代理中。

【讨论】:

  • 感谢您的解释!虽然,那么我如何通过 Spring 知道从 MyUserDetailsService 查找我的配置?
  • “传春知道”是什么意思?
  • 我的意思是:Spring 怎么知道从MyUserDetailsService 查找我的配置?抱歉,我在打字的时候打错了很多字。
  • 你的意思是,Spring 怎么会知道专门自动装配MyUserDetailsService?好吧,它会搜索所有实现UserDetailsService(字段类型)的bean,如果它找到一个,就会自动装配,否则会抛出异常。
  • @Roman,+1 分叉他的 repo 并建议修复。确实,开发人员喜欢 SO 和 Git!
【解决方案2】:

MyUserDetailsService 中删除@Transactional 有效。不知道为什么。如果有人有解释,请发布,我会将其标记为答案。

仔细检查,这确实是正确的,如果您想自己检查,请检查上面列出的存储库的commit 840f0753bdca1592d9070c74bc87f30e8e2f87a7,并进行测试。

别再否决这个答案,因为你认为这是不正确的。

【讨论】:

  • 这没有什么意义,你有没有机会在中间进行一些编辑?例如,UserF40 告诉您要做的更改,当您尝试它们时,您的项目没有重建,这就是它无法工作的原因?
  • @amingilani 如果您阅读@Transactional 并重建,它仍然有效吗?如果是这样,那并没有解决它。
  • @Jean-FrançoisSavard @UserF40,刚刚检查过,它不起作用。删除 @Transactional 使其工作。
【解决方案3】:

@ComponentScan 添加到 WebSecurityConfig。

由于component scanning,这应该在 MyUserDetailsS​​ervice 中连接,因为它带有 @Service 注释。

可以将包名作为参数传递给注解来设置组件扫描的范围,例如:

@ComponentScan("com.company.team")

【讨论】:

  • 这不是一个很好的解决方案。您隐藏了未扫描 bean 的事实。
  • @Service bean 也会被扫描。而没有使用扫描的事实真正的问题。
  • 注意,如果@ComponentScan中没有定义basePackageClasses,则扫描将从声明注解的类的包开始。
  • 没用。添加了@ComponentScan,以及@ComponentScan("myapp"),和@ComponentScan("myapp.MyUserDetailsService")
  • 为什么你在 github 上的 v2 项目中的包声明与文件所在的目录结构不匹配?
【解决方案4】:

请添加注解:@ComponentScan("") 在主配置类上。

如果您想为特定目录创建 bean/service,那么您可以在 @ComponentScan("package.to.scan") 中提供包路径

【讨论】:

    猜你喜欢
    • 2013-05-14
    • 2014-09-03
    • 2013-05-12
    • 2019-06-01
    • 2013-02-11
    • 1970-01-01
    • 2012-12-13
    • 2015-04-07
    • 2014-10-12
    相关资源
    最近更新 更多