ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Boot] application.properties에서 *.java로 property 가져오기
    개발기록 2022. 9. 6. 19:49
    반응형
    728x90

     

    개요

    구글링을 하면서 프로퍼티를 java파일로 가져오기위해 상당히 많은 삽질을 했다,,

    다음엔 안 그러기 위해 지금부터 기록을 남긴다.

     

    문제점

    application.properties에 key와 value를 선언하고

    ## 토큰 secretkey & 만료기간
    # App Properties , expire 1day
    
    jwtSecret= TEST_JwtSecretKey
    accJwtExpirationMs= 1000 * 60 * 30
    refJwtExpirationMs= 1000 * 60 * 60 * 24 * 14

    ※ cf) 1000 * 60 * 30처럼 수식으로 쓸 경우 int가 아닌 String 으로 인식한다. 따라서 1800000처럼 계산하여 작성해야한다.

     

     

    *.java에서 @Value를 사용하려 했으나 null / 0만 가져오는 이슈발생

    package ;
    
    import lombok.AccessLevel;
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public final class TokenUtils {
    
        @Value("${jwtSecret}")
        public static String jwtSecret;
    
        @Value("${accJwtExpirationMs}")
        private static  int accJwtExpirationMs;
    
        @Value("test String")
        private static String testString;
    
        public static String test() {
            log.info("**************accJwtExpirationMs: " + accJwtExpirationMs);  // 0
            log.info("**************jwtSecret: " + jwtSecret);  // null
            log.info("**************testString: " + testString);  // null
        }
    }

    원인: static 필드를 썼기때문으로 보임
    -> 'Spring에서는 정적 변수로 선언된 변수에는 Injection할 수 없다.' 고 함.

    출처: https://wildeveloperetrain.tistory.com/143

     

    따라서 "static @Value" 키워드로 구글링해서 해결책을 찾아보았다.

    참고: https://madplay.github.io/post/spring-framework-static-field-injection

     

    위 블로그에 따르면 static 필드에 setter와 constructor를 통해 injection을 할 수 있다고 되어있다.

    여기서는 @Value가 아닌 @Autowired이지만 참고해서 해결해보기로 했다.

     

    해결책

    해결책 1. setter를 통한 injection

    package ;
    
    import lombok.AccessLevel;
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public final class TokenUtils {
    
        public static String jwtSecret;
    
        // 해결책 1. setter를 통한 injection
        @Value("${jwtSecret}")
        public void setjwtSecret(String jwtSecret) {
            this.jwtSecret = jwtSecret;
        }
    
        public static String test() {
            log.info("**************accJwtExpirationMs: " + accJwtExpirationMs);  // 0
            log.info("**************jwtSecret: " + jwtSecret);  // TEST_JwtSecretKey
            log.info("**************testString: " + testString);  // null
        }
    }

     

    출처: https://jkpark.me/springboot/java/2020/06/04/Spring-Boot-static-%EB%B3%80%EC%88%98%EC%97%90%EC%84%9C-@value-annontation-%EC%82%AC%EC%9A%A9.html

     

    해결책2. constructor를 통한 injection

    package ;
    
    import lombok.AccessLevel;
    import lombok.NoArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    @NoArgsConstructor(access = AccessLevel.PRIVATE)
    public final class TokenUtils {
    
        public static String jwtSecret;
    
        // 해결책 1. setter를 통한 injection
        @Value("${jwtSecret}")
        public void setjwtSecret(String jwtSecret) {
            this.jwtSecret = jwtSecret;
        }
        
        // 해결책 2. constructor를 통한 injection - 컴파일에러
        @Value("${accJwtExpirationMs}")
        private TokenUtils(int accJwtExpirationMs) {
            this.accJwtExpirationMs = accJwtExpirationMs;
        }
    
        public static String test() {
            log.info("**************accJwtExpirationMs: " + accJwtExpirationMs);  // 0
            log.info("**************jwtSecret: " + jwtSecret);  // TEST_JwtSecretKey
            log.info("**************testString: " + testString);  // null
        }
    }

     

    컴파일 에러가 뜬다.

     

     

    @Value는 생성자에서 쓸 수 없다고 한다.

    따라서 앞으로 static 필드에 @Value를 통한 injection을 하고 싶다면 setter를 사용해서 해결하도록 하자.

     

    더 공부할 점

    +) 프로퍼티를 accJwtExpirationMs= 1000 * 60 * 30 처럼 수식을 쓰면 int 타입으로 받아올 수가 없다.

    1800000처럼 쓰면 위 방법처럼 해결이 된다.

    유지보수와 가독성을 생각했을 때 수식도 넘겨받을 수 있는 방법을 찾으면 좋을 것 같다.

    +) static일 경우 injection이 왜 안 되는 지에 대해 공부해볼 필요가 있겠다.

    +) 프로퍼티 값이 수식일 때 받는 법 찾기

    728x90
Designed by Tistory.