[SPRING]#3 Environment, Resource, Profile

eunseo·2021년 8월 19일
0

SPRING

목록 보기
3/14

Environment

ApplicationContext에서 제공하는 또 다른 중요한 기능중의 하나인 Environment에 대해서 살펴보자.

AppConfiguration

@SpringBootApplication을 이용하면 PropertySource안해도 된다!
기본으로 application.properties, application.yaml 파일을 읽기 때문이다.

OrderTester.java

getProperty를 통해 kdt.version값을 가져올 수 있다.

OrderProperties

package org.prgms.order;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;

@Component
public class OrderProperties implements InitializingBean {
    @Value("${kdt.version:v0.0.0}") // kdt.version 값을 못읽으면 v0.0.0 default 값
    private String  version;

    @Value("3")
    private Integer minimumOrderAmount;

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println(MessageFormat.format("version -> {0}", version));
        System.out.println(MessageFormat.format("minimumOrderAmount -> {0}",  minimumOrderAmount));
    }

}

값을 바꿀 수 있음. InitializingBean을 통해 먼저 호출 된다.!!

Resource를 이용하여 파일 읽기(application.properties, application.yaml)

application.properties

version = v1.0.0

kdt.version = v1.0.0

kdt.support-vendors = a,b,c,d,e,f,g

kdt.minimum-order-amount = 1

application.yaml

kdt:
  version: "v1.0.0"
  support-vendors:
    - a
    - b
    - c

스프링 Profile

스프링 프로파일은 애플리케이션 설정 일부를 분리하여 특정 환경에서만 사용 가능하다. 프로파일을 이용하면 여러 빈 정의들이 특정 프로파일에서만 동작하게 할수도 있고 특정 프로퍼티들을 특정 프로파일로 정의해서 해당 프로파일이 엑티브일때 적용되게 할 수도 있다. 빈 정의와 프로퍼티들에 프로파일을 적용해 보자.

우선 빈 정의시 프로파일을 적용

@Repository
@Profile("local")
public class MemoryVoucherRepository implements VoucherRepository, InitializingBean {
@Repository
@Profile("dev")
public class JdbcVoucherRepository implements VoucherRepository {
@Repository
@Profile("dev")
public class JdbcVoucherRepository implements VoucherRepository {
package org.prgrms.kdt;

import org.prgrms.kdt.order.OrderItem;
import org.prgrms.kdt.order.OrderProperties;
import org.prgrms.kdt.order.OrderService;
import org.prgrms.kdt.order.VersionProvider;
import org.prgrms.kdt.voucher.FixedAmountVoucher;
import org.prgrms.kdt.voucher.JdbcVoucherRepository;
import org.prgrms.kdt.voucher.VoucherRepository;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.util.Assert;

import java.text.MessageFormat;
import java.util.*;

public class OrderTester {

  public static void main(String[] args) {
  // 프로파일을 적용하고 리플레쉬를 해줘야합니다. 안그러면 이미 디폴트 프로파일로 읽어져서 원하는 결과를 얻을 수 없습니다.
    var applicationContext = new AnnotationConfigApplicationContext();
    applicationContext.getEnvironment().setActiveProfiles("dev");;
    applicationContext.register(AppConfiguration.class);
    applicationContext.refresh();
   
    var orderService = applicationContext.getBean(OrderService.class);
    var voucherRepository = applicationContext.getBean(VoucherRepository.class);

    System.out.println(MessageFormat.format("is JdbcRepo -> {0}", voucherRepository instanceof JdbcVoucherRepository));
    System.out.println(MessageFormat.format("is JdbcRepo -> {0}", voucherRepository.getClass().getCanonicalName()));

    var voucher = voucherRepository.insert(new FixedAmountVoucher(UUID.randomUUID(), 10L));
    var order = orderService.createOrder(UUID.randomUUID(), new ArrayList<OrderItem>() {{
      add(new OrderItem(UUID.randomUUID(), 100, 1));
    }}, voucher.getVoucherId());

    Assert.isTrue(order.totalAmount() == 90L,
      MessageFormat.format("totalAmount({0}) is not 90L", order.totalAmount()));
  }

}

다음으로 프로파일에 적용해 보자.

servers:
  - dev.bar.com
  - foo.bar.com

---

spring.config.activate.on-profile: local
kdt:
  version: v1.0
  support-vendors:
    - "a"
    - "b"
    - "c"
    - "d"
  minimum-order-amount: 1
  description: |- #-에 따라 마지막 줄마꿈이 포함되거나 안포함된다. -있으면 안포함
    line 1
    line 2
    line 3

---

spring.config.activate.on-profile: dev
kdt:
  version: v1.0-dev
  support-vendors:
    - "dev-a"
    - "dev-b"
  minimum-order-amount: 0
  description: |-
    dev

application.yml

var applicationContext = new AnnotationConfigApplicationContext();
applicationContext.getEnvironment().setActiveProfiles("dev");;
applicationContext.register(AppConfiguration.class);
applicationContext.refresh();

var version = applicationContext.getEnvironment().getProperty("kdt.version");
var supportVendors = applicationContext.getEnvironment().getProperty("kdt.support-vendors");
var description = applicationContext.getEnvironment().getProperty("kdt.description");
System.out.println(MessageFormat.format("getVersion from env -> {0}", version));
System.out.println(MessageFormat.format("supportVendors from env -> {0}", supportVendors));
System.out.println(MessageFormat.format("description from env -> {0}", description));

var orderProperties = applicationContext.getBean(OrderProperties.class);
System.out.println(MessageFormat.format("getVersion -> {0}", orderProperties.getVersion()));
System.out.println(MessageFormat.format("getMinimumOrderAmount -> {0}", orderProperties.getMinimumOrderAmount()));
System.out.println(MessageFormat.format("getSupportVendors -> {0}", orderProperties.getSupportVendors()));
System.out.println(MessageFormat.format("description -> {0}", orderProperties.getDescription()));

dev → local로 변경하면 이상하게 프로퍼티는 안바뀌지만 주입되는 빈은 변경되는 것을 볼 수있습니다. 스프링 프레임워크는 프로파일에 대한 빈 정의 만을 지원하고 사실 프로파일별 프로퍼티에 대한 변경은 스프링부트에서 지원하는 기능입니다.

스프링부트의 SpringApplication를 사용하기 전에 우선 활성 프로파일을 정의할수 있는 다른 방법들을 보겠습니다.

스프링 활성 프로파일에 대한 정의는 다양한 곳에서 가능합니다. 방금 한 것 처럼 애플리케이션 코드상에 직접 세팅할 수도 있지만 JVM의 시스템 속성 ,명령줄 인수, OS의 환경변수, 프로퍼티의 속성에서도 가능합니다.

하나씩 한번 살펴보도록 할게요.

그럼 이제 KdtApplication 을 변경해볼가요.

package org.prgrms.kdt;

import org.prgrms.kdt.order.Order;
import org.prgrms.kdt.order.OrderProperties;
import org.prgrms.kdt.order.OrderRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import java.text.MessageFormat;

@SpringBootApplication
@ComponentScan(basePackages = {"org.prgrms.kdt.order", "org.prgrms.kdt.voucher", "org.prgrms.kdt.config"})
public class KdtApplication {

  public static void main(String[] args) {
    var context = SpringApplication.run(KdtApplication.class, args);
    var orderProperties = context.getBean(OrderProperties.class);
    System.out.println(MessageFormat.format("getVersion -> {0}", orderProperties.getVersion()));
    System.out.println(MessageFormat.format("getMinimumOrderAmount -> {0}", orderProperties.getMinimumOrderAmount()));
    System.out.println(MessageFormat.format("getSupportVendors -> {0}", orderProperties.getSupportVendors()));
    System.out.println(MessageFormat.format("getDescription -> {0}", orderProperties.getDescription()));
  }

}

코드상에서 변경하려면 다음과 같이 해야합니다.

var springApplication = new SpringApplication(KdtApplication.class);
springApplication.setAdditionalProfiles("dev");
var context = springApplication.run();

springApplication.setAdditionalProfiles("dev");이거를 쓰지 않고
스프링 부트에서는 설정할 수 있는 방법이 다양하다.(Edit configuration)

  1. Active profiles에 dev라고 설정하기( 밑에 사진 참조)

  2. Program argument에 설정하기( --spring.profiles.active = local)

profile
backend developer

0개의 댓글

관련 채용 정보