问题描述
我最近回到了我一直在从事的Spring项目,并且在启动该应用程序时遇到了问题.这个问题可能是重复的,但我一直找不到答案.
I recently came back to a Spring project I'd been working on and I've run into issues when starting up the app. This question is probably a duplicate, but I haven't been able to find an answer.
这是我原始的SecurityConfig.java中的摘录:
Here's a snippet from my original SecurityConfig.java:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private UserService userService;
/**
* Global security config to set the user details service etc.
* @param auth authentication manager
* @throws Exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userService)
.passwordEncoder(passwordEncoder());
}
UserService对象实现UserDetailsService.这给启动时带来了错误:
The UserService object implements UserDetailsService. This gave the error on startup:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.clubmate.web.service.UserService com.clubmate.web.config.SecurityConfig.userService; nested exception is java.lang.IllegalArgumentException: Can not set com.clubmate.web.service.UserService field com.clubmate.web.config.SecurityConfig.userService to com.sun.proxy.$Proxy62
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 58 more
Caused by: java.lang.IllegalArgumentException: Can not set com.clubmate.web.service.UserService field com.clubmate.web.config.SecurityConfig.userService to com.sun.proxy.$Proxy62
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:764)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569)
... 60 more
根据我的阅读,这是因为我正在自动装配具体的类而不是UserDetailsService接口,但这对我来说很奇怪,因为在我以前从事此项目时,自动装配具体的类工作正常.
From my reading, this is because I'm autowiring a concrete class instead of the UserDetailsService interface, but this is strange to me, because when I worked on this project before, autowiring the concrete class worked fine.
我屈服了,只是对其进行了更改,以自动装配SecurityConfig.java中的UserDetailsService接口.
I gave in and just changed it to autowire the UserDetailsService interface in SecurityConfig.java.
我不确定这是否相关,但是现在在启动时,对于我的任何其他具有@Autowire private UserService userService
的bean对象(@Service
s等),都会收到以下错误.
I'm not sure whether this is related or not, but now on startup I get the below error, for any of my other bean objects (@Service
s etc.) that have @Autowire private UserService userService
.
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.clubmate.web.service.UserService com.clubmate.web.service.PageService.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.clubmate.web.service.UserService] 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$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 58 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.clubmate.web.service.UserService] 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.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 60 more
任何帮助,我们将不胜感激.这使我疯了几个小时.
Any help greatly appreciated. This has been driving me nuts for hours.
更新
更多信息:我还有另一个配置类(AppConfig.java),其内容如下:
More info: I have another config class (AppConfig.java) with the following:
@Configuration
@EnableWebMvc
@ComponentScan("com.clubmate.web")
@PropertySource(value = { "classpath:application.properties" })
@Import({
SecurityConfig.class,
CacheConfig.class,
DatabaseConfig.class,
CronConfig.class
})
public class AppConfig extends WebMvcConfigurerAdapter {
// ...
}
我也有两个应用程序初始化程序类,其中一个用于MVC:
I also have two app initializer classes, one for MVC which is:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
public Class<?>[] getRootConfigClasses() {
return new Class[] {
AppConfig.class
};
}
@Override
public Class<?>[] getServletConfigClasses() {
return new Class[] {
StartupHousekeeping.class,
ShutdownHousekeeping.class
};
}
@Override
public String[] getServletMappings() {
return new String[] {
"/"
};
}
}
...还有另一个安全性方面的信息:
...and another for Security which is:
public class AppInitializer extends AbstractSecurityWebApplicationInitializer {
private static Logger log = LogManager.getLogger(AppInitializer.class);
@Override
protected void beforeSpringSecurityFilterChain(ServletContext context) {
// load multipart filter before other filters are created
// see: http://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#csrf-multipart
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
insertFilters(context, multipartFilter);
}
}
这些会以某种方式发生冲突吗?
Could these be conflicting somehow?
更新2
引发异常的地方的屏幕截图: http://i.imgur.com/r6AsOob.jpg
Screenshot of where the exception is being thrown: http://i.imgur.com/r6AsOob.jpg
var1是SecurityConfig类,var2是Proxy对象,而应该是我的UserService类.
var1 is the SecurityConfig class, var2 is a Proxy object, which should instead be my UserService class.
推荐答案
自动装配失败,因为默认情况下,Spring使用JDK动态代理(通过实现目标接口来代理目标类)创建代理.另一方面,基于CGLIB的代理是目标类的子类.
The autowiring fails because by default Spring creates proxies using JDK-dynamic proxies (which proxies the target class by implementing its interface(s)).CGLIB-based proxies on the other hand are subclasses of the target class.
要启用基于CGLIB的代理,请使用@EnableAspectJAutoProxy(proxyTargetClass=true)
注释您的@Configuration
类之一:
To enable CGLIB based proxying annotate one of your @Configuration
classes with @EnableAspectJAutoProxy(proxyTargetClass=true)
:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
...
}
这篇关于Spring Security配置自动装配自定义UserDetailsService bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!