Java Spring组件扫描故障
我正在使用Hibernate和SpringSecurity(带有小tic-tac-toe游戏的基本日志表单)制作一个SpringMaven项目。由于我决定不使用单根WebApplicationContext并将其划分为根和Servlet上下文,所以一切正常(有人告诉我,使用单根WebApplicationContext是不正确的,因为您可以将@Autowire controller放入存储库或服务中,这是禁止的) 以下是我的项目结构: ServletConfig类:Java Spring组件扫描故障,java,spring,hibernate,maven,spring-mvc,Java,Spring,Hibernate,Maven,Spring Mvc,我正在使用Hibernate和SpringSecurity(带有小tic-tac-toe游戏的基本日志表单)制作一个SpringMaven项目。由于我决定不使用单根WebApplicationContext并将其划分为根和Servlet上下文,所以一切正常(有人告诉我,使用单根WebApplicationContext是不正确的,因为您可以将@Autowire controller放入存储库或服务中,这是禁止的) 以下是我的项目结构: ServletConfig类: @EnableWebMvc
@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/");
}
}
@Configuration
@ComponentScan(basePackages = {"services","dao"})
public class RootConfig {
}
RootConfig类:
@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/");
}
}
@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[]{"/"};
}
}
用于以这种方式注入:
this.userService = (UserService) ApplicationContextHolder.getContext().getBean("userService");
当我试图通过Tomcat运行它时,我得到一个错误:
2016-11-20 17:09:54警告注释ConfigWebApplicationContext:549-上下文初始化期间遇到异常-取消刷新尝试:org.springframework.beans.factory.UnsatifiedDependencyException:创建名为“roleServiceImpl”的bean时出错:通过字段“dao”表示的未满足的依赖关系;嵌套异常是org.springframework.beans.factory.UnsatifiedDependencyException:创建名为“roleDaoImpl”的bean时出错:通过字段“sessionFactory”表示未满足的依赖关系;嵌套异常是
org.springframework.beans.factory.NoSuchBeanDefinitionException:未找到符合依赖项[org.hibernate.SessionFactory]条件的bean:至少需要1个符合autowire候选项条件的bean。依赖项注释:{@org.springframework.beans.factory.annotation.Autowired(required=true)} 2016-11-20 17:09:54错误ContextLoader:351-上下文初始化失败 org.springframework.beans.factory.UnsatifiedDependencyException:创建名为“roleServiceImpl”的bean时出错:通过字段“dao”表示未满足的依赖关系;嵌套异常是
org.springframework.beans.factory.UnsatifiedDependencyException:创建名为“roleDaoImpl”的bean时出错:通过字段“sessionFactory”表示未满足的依赖关系;嵌套异常是
org.springframework.beans.factory.NoSuchBeanDefinitionException:未找到符合依赖项[org.hibernate.SessionFactory]条件的bean:至少需要1个符合autowire候选项条件的bean。依赖项注释:{@org.springframework.beans.factory.annotation.Autowired(required=true)} 以下是我的问题:
@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;
}
}
@编辑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:
@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;
}
}
@Data
public class Game {
@Autowired
private UserService userService; ....
public Game() {
this.userService = (UserService) ApplicationContextHolder.getContext().getBean("userService");
}
我建议您将所有包放在一个公共包(如“com.app”)下面,并在com.app中创建一个带有@SpringBootApplication注释的类应用程序。该注释包括一个componentScan,可以扫描所有子包。谢谢。使用这样的配置在测试目录中创建@Autowired字段会有任何问题吗?您如何使用ApplicationContextHolder,您能否显示类在测试目录中具有@Autowired?您必须确保只有测试类对该bean具有依赖性,否则Spring将不会启动,因为它不会扫描测试目录——即使它有相同的包。您的意思是“因为我的一个类必须使用new()创建,并且还需要自动连接我正在使用的ApplicationContextHolder中的一个服务:”。您的意思是说您的服务没有空构造函数吗?您的配置对于组件扫描是正确的,但缺少hibernate配置,这就是它失败的原因。正如您在错误中看到的,您缺少
org.hibernate.SessionFactory
bean,您在roledoaimpl
中有@Autowire
d。我建议您将所有包放在一个公共包(如“com.app”)下面,并在com.app中创建一个带有@springbootcapplication注释的类应用程序。该注释包括一个componentScan,可以扫描所有子包。谢谢。使用这样的配置在测试目录中创建@Autowired字段会有任何问题吗?您如何使用ApplicationContextHolder,您能否显示类在测试目录中具有@Autowired?您必须确保只有测试类对该bean具有依赖性,否则Spring将不会启动,因为它不会扫描测试目录——即使它有相同的包。您的意思是“因为我的一个类必须使用new()创建,并且还需要自动连接我正在使用的ApplicationContextHolder中的一个服务:”。您的意思是说您的服务没有空构造函数吗?您的配置对于组件扫描是正确的,但缺少hibernate配置,这就是它失败的原因。正如您在错误中看到的,您缺少org.hibernate.SessionFactory
bean,该bean位于roleDaoImpl
中的@Autowire
d。