我刚开始尝试使用
spring boot和jsp创建一个web应用程序,我可以在覆盆子pi上使用tomcat8进行部署.我可以通过嵌入式tomcat实例上的sts部署我的应用程序,我也可以将一个war文件部署到Jenkins而不会出现任何错误.但是,当我将战争添加到tomcat8 webapps文件夹并启动tomcat时,我收到以下错误:
2016-04-19 10:54:41.384 WARN 5525 --- [ost-startStop-1] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.rcctv.controllers.UserController.setUserService(com.rcctv.services.UserService); nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl' defined in file [/usr/share/tomcat8/webapps/RaspberryCCTV-0.0.1-SNAPSHOT/WEB-INF/classes/com/rcctv/services/UserServiceImpl.class]: Unsatisfied dependency expressed through constructor argument with index 1 of type [org.springframework.security.crypto.password.PasswordEncoder]: : Error creating bean with name 'webSecurityConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userServiceImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'webSecurityConfig': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userServiceImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
我尝试用@Lazy注释我的配置类,并在我的userServiceImpl类中添加了setter方法,但我仍然遇到了问题.任何帮助将不胜感激?
webConfig类
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${rememberMe.privateKey}")
private String rememberMeKey;
@Value("${spring.profiles.active}")
private String env;
@Resource
private UserDetailsService userService;
@Bean
public HibernateJpaSessionFactoryBean sessionFactory() {
return new HibernateJpaSessionFactoryBean();
}
@Bean
public RememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices(rememberMeKey, userService);
return rememberMeServices;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/",
"/home",
"/error",
"/signup",
"/forgot-password",
"/reset-password/*",
"/public/**",
"/users/*").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/raspberrycctv")
.permitAll().and()
.rememberMe().key(rememberMeKey).rememberMeServices(rememberMeServices()).and()
.logout()
.permitAll();
if (!env.equals("dev"))
http.requiresChannel().anyRequest().requiresSecure();
}
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
}
UserSeviceImpl
@Service
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class UserServiceImpl implements UserService, UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
private MailSender mailSender;
@Autowired
public UserServiceImpl(UserRepository userRepository,
PasswordEncoder passwordEncoder,
MailSender mailSender) {
this.mailSender = mailSender;
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Autowired
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@Autowired
public void setMailSender(MailSender mailSender) {
this.mailSender = mailSender;
}
@Override
@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void signup(SignupForm signupForm) {
final User user = new User();
user.setEmail(signupForm.getEmail());
user.setName(signupForm.getName());
user.setPassword(passwordEncoder.encode(signupForm.getPassword()));
user.getRoles().add(Role.UNVERIFIED);
user.setVerificationCode(RandomStringUtils.randomAlphanumeric(16));
userRepository.save(user);
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
try {
String verifyLink = Utilities.hostUrl() + "/users/" + user.getVerificationCode() + "/verify";
mailSender.send(user.getEmail(), Utilities.getMessage("verifySubject"), Utilities.getMessage("verifyEmail", verifyLink));
logger.info("Verification mail to " + user.getEmail() + " queued.");
} catch (MessagingException e) {
logger.error(ExceptionUtils.getStackTrace(e));
}
}
});
}
}
最佳答案 我认为你应该通过
Spring Reference关于IoC容器.
WebSecurityConfig类需要UserDetailsService,它由UserServiceImpl实现.此外,UserServiceImpl需要由WebSecurityConfig提供的PasswordEncoder.这会导致循环引用.删除构造函数注入应足以解决您的问题.
旁注:尽量不要使用构造函数注入.对于DI来说,Spring很聪明,但是如果使用构造函数注入,那么就是强迫spring使用你的方式.这也可能导致循环引用错误.
我建议你至少浏览一下这篇文章:https://steveschols.wordpress.com/2012/06/05/i-was-wrong-constructor-vs-setter-injection/