我正在使用Hibernate和Spring Security制作Spring Maven项目(基本的日志记录形式,带有小小的井字游戏)。一切正常,因为我决定不使用单个Root WebApplicationContext并将其划分为Root和Servlet Context(我被告知使用单一的是不正确的,因为你可以@Autowire控制器进入存储库或服务被禁止)。
这是我的项目结构:
ServletConfig类:
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"controller"})
public class ServletConfig extends WebMvcConfigurerAdapter {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
RootConfig类:
@Configuration
@ComponentScan(basePackages = {"services","dao"})
public class RootConfig {
}
WebAppInitializer:
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class};
}
protected Class<?>[] getServletConfigClasses() {return new Class[]{ServletConfig.class};}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
因为我的一个类必须用new()创建,并且还需要自动装配我正在使用ApplicationContextHolder的服务之一:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
用于以这种方式注入:
this.userService = (UserService) ApplicationContextHolder.getContext().getBean("userService");
当我尝试通过Tomcat运行它时,我得到一个错误:
2016-11-20 17:09:54 WARN AnnotationConfigWebApplicationContext:549 - 在上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'roleServiceImpl'的bean时出错:表示不满意的依赖关系通过字段'dao';嵌套异常是
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'roleDaoImpl'的bean时出错:通过字段'sessionFactory'表示的不满意的依赖关系;嵌套异常是
org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到依赖项[org.hibernate.SessionFactory]的限定bean:预计至少有1个bean可以作为autowire候选者。依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)} 2016-11-20 17:09:54错误ContextLoader:351 - 上下文初始化失败 org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'roleServiceImpl'的bean时出错:通过字段'dao'表示的不满意的依赖关系;嵌套异常是
org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'roleDaoImpl'的bean时出错:通过字段'sessionFactory'表示的不满意的依赖关系;嵌套异常是
org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到依赖项[org.hibernate.SessionFactory]的限定bean:预计至少有1个bean可以作为autowire候选者。依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true)}
以下是我的问题:
是否可以只使用一个Config类?就像: @ComponentScan( “一切”)?
我是否必须使用Root或Servlet配置类中的Spring Security配置扫描包?
@EDIT 1:
这是我的ApplicationContextHolder类
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
@EDIT 2:
HibernateConfiguration类:
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com/configuration")
@PropertySource(value = {"classpath:application.properties"})
public class HibernateConfiguration {
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("com.entities");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory);
return transactionManager;
}
}
我在这里使用的是AppContextHolder:
@Data
public class Game {
@Autowired
private UserService userService; ....
public Game() {
this.userService = (UserService) ApplicationContextHolder.getContext().getBean("userService");
}