복붙노트

[SPRING] Spring MVC, 하나의 설정 대신 두 개의 설정 인스턴스

SPRING

Spring MVC, 하나의 설정 대신 두 개의 설정 인스턴스

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>

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을 만들고 싶습니다. 이것을 달성하는 방법? 두 번째 질문은 청취자는 무엇을합니까?

해결법

  1. ==============================

    1.여기서 문제는 서블릿과 루트 컨텍스트에 대해 동일한 구성을 사용하고 있다는 것입니다. 이유는 두 가지 구성 인스턴스가있는 이유입니다. Spring MVC에서는 서블릿 컨텍스트와 루트 컨텍스트라는 두 가지 컨텍스트가있다. 서블릿 컨텍스트는 컨트롤러 용이고 비즈니스 개체 및 서비스 용 루트 컨텍스트입니다.

    여기서 문제는 서블릿과 루트 컨텍스트에 대해 동일한 구성을 사용하고 있다는 것입니다. 이유는 두 가지 구성 인스턴스가있는 이유입니다. Spring MVC에서는 서블릿 컨텍스트와 루트 컨텍스트라는 두 가지 컨텍스트가있다. 서블릿 컨텍스트는 컨트롤러 용이고 비즈니스 개체 및 서비스 용 루트 컨텍스트입니다.

    XML을 사용하지 않으려면 두 개의 config 클래스를 만듭니다. 이 같은 :

    루트 컨텍스트 :

    @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 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>
    
  2. ==============================

    2.나는 @Configuration 클래스를 Component 검색을 통해 식별하는 대신 ContextConfigLocation으로 포함시킴으로써 중복 ListableBeanFactories가 생성되고 Hibernate SessionFactory를 잠글 때 메모리 누수를 피할 수 있음을 발견했다.

    나는 @Configuration 클래스를 Component 검색을 통해 식별하는 대신 ContextConfigLocation으로 포함시킴으로써 중복 ListableBeanFactories가 생성되고 Hibernate SessionFactory를 잠글 때 메모리 누수를 피할 수 있음을 발견했다.

  3. from https://stackoverflow.com/questions/14206564/spring-mvc-two-instances-of-configuration-instead-of-one by cc-by-sa and MIT license