Autowire 不适用于 Spring Boot 中的自定义 UserDetailsService
Autowire doesn't work for custom UserDetailsService in Spring Boot
spring 引导应用程序启动,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
找到完整的源代码
将 @ComponentScan
添加到 WebSecurityConfig。
由于 component scanning,这应该连接到 MyUserDetailsService 中,因为它被注释为 @Service
。
可以将包名作为参数传递给注解来设置组件扫描的范围,例如:
@ComponentScan("com.company.team")
从 MyUserDetailsService
中删除 @Transactional
成功了。不知道为什么。如果有人有解释,请post,我会将其标记为答案。
仔细检查,这确实是正确的,如果您想自己检查,请检查上面列出的存储库的提交 840f0753bdca1592d9070c74bc87f30e8e2f87a7
,并进行测试。
并停止否决这个答案,因为你认为它是不正确的。
请添加注释:@ComponentScan("")
在主配置上 class.
如果你想为特定目录创建bean/service那么你可以在@ComponentScan("package.to.scan")
中给出包路径
我在提交 3b9a6a2e
时尝试了你的项目,错误实际上是不同的:
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
这使您的问题与 Spring can't create beans 重复。解决方法:替换
@Autowired
private MyUserDetailsService userDetailsService;
和
@Autowired
private UserDetailsService userDetailsService;
您的解决方案(删除 @Transactional
)有效,因为如果没有 @Transactional
,Spring 就没有理由将 MyUserDetailsService
包装在代理中。
spring 引导应用程序启动,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
找到完整的源代码将 @ComponentScan
添加到 WebSecurityConfig。
由于 component scanning,这应该连接到 MyUserDetailsService 中,因为它被注释为 @Service
。
可以将包名作为参数传递给注解来设置组件扫描的范围,例如:
@ComponentScan("com.company.team")
从 MyUserDetailsService
中删除 @Transactional
成功了。不知道为什么。如果有人有解释,请post,我会将其标记为答案。
仔细检查,这确实是正确的,如果您想自己检查,请检查上面列出的存储库的提交 840f0753bdca1592d9070c74bc87f30e8e2f87a7
,并进行测试。
并停止否决这个答案,因为你认为它是不正确的。
请添加注释:@ComponentScan("")
在主配置上 class.
如果你想为特定目录创建bean/service那么你可以在@ComponentScan("package.to.scan")
我在提交 3b9a6a2e
时尝试了你的项目,错误实际上是不同的:
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
这使您的问题与 Spring can't create beans 重复。解决方法:替换
@Autowired
private MyUserDetailsService userDetailsService;
和
@Autowired
private UserDetailsService userDetailsService;
您的解决方案(删除 @Transactional
)有效,因为如果没有 @Transactional
,Spring 就没有理由将 MyUserDetailsService
包装在代理中。