3

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

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
  <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
       instead of the default XmlWebApplicationContext -->
  <context-param>
      <param-name>contextClass</param-name>
      <param-value>
          org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
  </context-param>

  <!-- Configuration locations must consist of one or more comma- or space-delimited
       fully-qualified @Configuration classes. Fully-qualified packages may also be
       specified for component-scanning -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
  </context-param>

  <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Declare a Spring MVC DispatcherServlet as usual -->
  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
           instead of the default XmlWebApplicationContext -->
      <init-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </init-param>
      <!-- Again, config locations must consist of one or more comma- or space-delimited
           and fully-qualified @Configuration classes -->
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
      </init-param>
  </servlet>

  <!-- map all requests for / to the dispatcher servlet -->
  <servlet-mapping>
      <servlet-name>dispatcher</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

应用配置.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。如何做到这一点?第二个问题,听众做什么?

4

2 回答 2

4

这里的问题是您对 servlet 和根上下文使用相同的配置。这就是为什么你有两个配置实例。在 Spring MVC 中,您有 2 个上下文,即 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());   
    }
}

小服务程序上下文

@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;
    }
}

网页.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
        version="3.0">
      <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
           instead of the default XmlWebApplicationContext -->
      <context-param>
          <param-name>contextClass</param-name>
          <param-value>
              org.springframework.web.context.support.AnnotationConfigWebApplicationContext
          </param-value>
      </context-param>

      <!-- Configuration locations must consist of one or more comma- or space-delimited
           fully-qualified @Configuration classes. Fully-qualified packages may also be
           specified for component-scanning -->
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>pl.mbrnwsk.sklep.config.AppConfiguration</param-value>
      </context-param>

      <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

      <!-- Declare a Spring MVC DispatcherServlet as usual -->
      <servlet>
          <servlet-name>dispatcher</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
               instead of the default XmlWebApplicationContext -->
          <init-param>
              <param-name>contextClass</param-name>
              <param-value>
                  org.springframework.web.context.support.AnnotationConfigWebApplicationContext
              </param-value>
          </init-param>
          <!-- Again, config locations must consist of one or more comma- or space-delimited
               and fully-qualified @Configuration classes -->
          <init-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>pl.mbrnwsk.sklep.config.ServletConfiguration</param-value>
          </init-param>
      </servlet>

      <!-- map all requests for / to the dispatcher servlet -->
      <servlet-mapping>
          <servlet-name>dispatcher</servlet-name>
          <url-pattern>/</url-pattern>
      </servlet-mapping>
</web-app>
于 2013-01-08T03:52:31.470 回答
0

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

于 2013-10-28T17:42:25.700 回答