Spring MVC,两个配置实例而不是一个

我开始学习Spring MVC了。 我正试图摆脱所有Spring XML配置。 这是我的web.xml:

    contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext     contextConfigLocation pl.mbrnwsk.sklep.config.AppConfiguration    org.springframework.web.context.ContextLoaderListener    dispatcher org.springframework.web.servlet.DispatcherServlet   contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext     contextConfigLocation pl.mbrnwsk.sklep.config.AppConfiguration     dispatcher /   

Appconfiguration.java:

 @Configuration @EnableTransactionManagement @ComponentScan("pl.mbrnwsk.sklep") public class AppConfiguration { public String hbm2ddl_auto = "update"; public AppConfiguration(){ System.out.println("AppConfiguration"); } @Bean public ViewResolver viewResolver(){ InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Bean public DataSource dataSource() { DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("org.hsqldb.jdbcDriver"); ds.setUrl("jdbc:hsqldb:file:/SklepDB/"); ds.setUsername("SA"); ds.setPassword(""); return ds; } @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder ss = new LocalSessionFactoryBuilder(dataSource()); ss.scanPackages("pl.mbrnwsk.sklep.model"); ss.setProperty("hibernate.show_sql", "true"); ss.setProperty("hibernate.hbm2ddl.auto", hbm2ddl_auto); ss.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); return ss.buildSessionFactory(); } @Bean public PlatformTransactionManager txManager(){ return new HibernateTransactionManager(sessionFactory()); } } 

AppConfiguration的实例正在创建两次:一次是在我启动Tomcat时,两次是在我输入一些应该由调度程序处理的URL时。 这不是期望的行为。 我想在Tomcat启动时创建AppConfiguration。 怎么做到这一点? 第二个问题,听众做了什么?

这里的问题是您对servlet和根上下文使用相同的配置。 这就是为什么你有两个配置实例。 在Spring MVC中,您有两个上下文,即servlet上下文和根上下文。 servlet上下文适用于您的控制器以及业务对象和服务的根上下文。

如果您不想使用XML,请创建两个配置类。 像这样的东西:

根上下文

 @Configuration @EnableTransactionManagement @ComponentScan("pl.mbrnwsk.sklep") public class AppConfiguration { public String hbm2ddl_auto = "update"; public AppConfiguration(){ System.out.println("AppConfiguration"); } @Bean public DataSource dataSource() { DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("org.hsqldb.jdbcDriver"); ds.setUrl("jdbc:hsqldb:file:/SklepDB/"); ds.setUsername("SA"); ds.setPassword(""); return ds; } @Bean public SessionFactory sessionFactory() { LocalSessionFactoryBuilder ss = new LocalSessionFactoryBuilder(dataSource()); ss.scanPackages("pl.mbrnwsk.sklep.model"); ss.setProperty("hibernate.show_sql", "true"); ss.setProperty("hibernate.hbm2ddl.auto", hbm2ddl_auto); ss.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); return ss.buildSessionFactory(); } @Bean public PlatformTransactionManager txManager(){ return new HibernateTransactionManager(sessionFactory()); } } 

Servlet上下文

 @Configuration @ComponentScan("pl.mbrnwsk.sklep.controller") public class ServletConfiguration { public AppConfiguration(){ System.out.println("ServletConfiguration"); } @Bean public ViewResolver viewResolver(){ InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/"); viewResolver.setSuffix(".jsp"); return viewResolver; } } 

Web.xml

     contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext     contextConfigLocation pl.mbrnwsk.sklep.config.AppConfiguration    org.springframework.web.context.ContextLoaderListener    dispatcher org.springframework.web.servlet.DispatcherServlet   contextClass  org.springframework.web.context.support.AnnotationConfigWebApplicationContext     contextConfigLocation pl.mbrnwsk.sklep.config.ServletConfiguration     dispatcher /   

我发现通过将我的@Configuration类包含为ContextConfigLocation而不是通过组件扫描来识别它们,我避免了内存泄漏,其中将创建重复的ListableBeanFactories并锁定Hibernate SessionFactory。