Spring 설정을 XML에서 Java Config로 바꾸기

2020. 3. 27. 17:22Java/Spring

728x90

Spring 설정을 XML에서 Java Config로 하는 이유

  • 수정 시 재배포는 XML이든 Java Config든 같음
  • XML은 문서가 길어지면 가독성이 좋지 않음
  • XML은 단지 문서일 뿐이므로 휴먼 에러를 인지하는 타이밍이 컴파일 단계에서 알아 차릴 수 있는 Java Config보다 느림
  • Annotation 메타 정보 활용

Annotation을 이용한 프로그래밍 방식이란, Java 리플렉션 API를 이용해 Annotation의 메타 정보를 조회하고, Annotation 내에 설정된 값을 가져와 작업을 수행합니다. Anotation은 Spring이 참조하는 메타 정보로 사용되기 때문에 유리한 점이 많습니다.

  • Spring 설정 파일을 따로 관리할 필요가 없음
  • XML보다 명료함(XML은 설정이 많아지면 파일 길이가 길어져 가독성이 떨어짐)
  • 설정 코드에 Break Point를 걸어서 디버깅 할 수 있음

XML 설정을 Java Config 설정으로 변경하기

Dependecy 설정

Servlet-api 버전 3.0 이상을 사용합니다. Web.xml을 없애기 위해서는 Servlet 3.0 이상의 스펙이 필요합니다.

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>{{3.0 버전 이상}}</version>
    <scope>provided</scope>
</dependency>

Root-context.xml 제거하기

Root-context에는 주로 프로퍼티 홀더 설정이나 datasource 같이 여러 서블릿에서 공통으로 사용할 설정이 들어갑니다.

@Configuration
@PropertySource("classpath:/database.properties")
public class DataBaseConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username")
    private String username;
    @Value("${jdbc.password")
    private String password;

    @Bean
    public DataSource dataSource() {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName(driver);
        basicDataSource.setUrl(url);
        basicDataSource.setUsername(username);
        basicDataSource.setPassword(password);
        return basicDataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource());
        return dataSourceTransactionManager;
    }
}

클래스에 @Configuration Annotation을 붙여줍니다. 이는 설정용 클래스라는 것을 스프링에게 알려주는 역할입니다.

빈으로 만들어지길 원하는 객체를 리턴하는 메소드를 만들어줍니다. 이 메소드 내에 빈의 필요한 설정을 해주고 그것을 리턴합니다. 그리고 빈으로 등록되길 원하는 메소드에는 @Bean Annotaion을 붙여줍니다. 이 Annotation이 있어야 스프링이 빈으로 만들어줍니다.

Trasaction관리를 위해 PlatformTransactionManager의 구현 클래스를 빈으로 등록합니다. 그리고 Transaction 관리를 사용하겠다는 것을 알려주기 위해 @EnableTransactionManagement Annotation을 클래스에 붙여줍니다.

Servlet-context.xml 제거하기

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.navercorp.photith.controller"})
public class WebMvcConfig implements WebMvcConfigurer {
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
        internalResourceViewResolver.setPrefix("/WEB-INF/views/");
        internalResourceViewResolver.setSuffix(".jsp");
        return internalResourceViewResolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/");
        registry.addResourceHandler("/image/**").addResourceLocations("classpath:/static/image/");
        registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/");
    }
} 

@EnableWebMvc Annotation을 클래스에 붙여서 WebMvc관련 설정을 등록한다는 것을 알려줍니다. ResourceHandlerRegistry에 Resource 패턴과 Location을 매핑해서 등록해줍니다. 이와 같은 설정을 하기 위해서는 WebMvcConfigurer 인터페이스를 구현해줍니다.

혹은 WebMvcConfigurationSupport를 상속 받으면 @EnableWebMvc Annotation을 붙이지 않고 설정을 등록하고 ResourceHandler나 Interceptor 등을 사용자 설정에 맞추어 변경할 수 있습니다.

Web.xml 제거하기

    public class ServiceInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ApplicationConfig.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));
        this.addDispatcherServlet(servletContext);
        this.addUtf8CharacterEncodingFilter(servletContext);
    }

    private void addDispatcherServlet(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.register(WebMvcConfig.class);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
            new DispatcherServlet(applicationContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    private void addUtf8CharacterEncodingFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic filter = servletContext.addFilter("CHARACTER_ENCODING_FILTER",
            CharacterEncodingFilter.class);
        filter.setInitParameter("encoding", "UTF-8");
        filter.setInitParameter("forceEncoding", "true");
        filter.addMappingForUrlPatterns(null, false, "/*");
    }
}

WebApplicationInitializer Interface를 구현한 클래스를 만듭니다. 이 클래스는 web.xml의 역할을 대신할 클래스입니다.

onStartup() 메소드를 override합니다. 이 메소드는 서블릿 컨테이너가 실행될 때 자동으로 호출됩니다. 여기서 서블릿 컨텍스트에 앞서 설정한 ApplicationConfig의 내용을 등록합니다. 그리고 WebMvcConfig의 내용을 바탕으로 Dispatcher Servlet을 생성해 서블릿 컨텍스트에 등록합니다. Encoding Filter 또한 서블릿 컨텍스트에 등록해줍니다.

728x90

'Java > Spring' 카테고리의 다른 글

Spring Singleton  (0) 2020.05.01
@ExceptionHandler  (0) 2020.04.26
AOP  (0) 2020.04.18
@Transactional  (0) 2020.04.17
Spring DI 방법  (0) 2020.03.27