Spring 의 새로운 클래스
오늘 이야기 할 내용은 Spring과 Spring boot의 새로운 클래스에 대해서 알아보려고 한다. 제목은 Spring 이라고 했지만 Spring boot 도 포함되어 있다. 대략 4가지 정도 클래스를 알아볼 예정인데 각 설명마다 프로젝트와 버전을 명시하겠다.
보다 많은 클래스가 추가 되었지만 다 알아 볼 수도 없고 또 한 클래스들이 디펜더시도 있어 유틸성의 클래스들만 알아보도록 하자.
DataSize
DataSize 클래스는 Spring 5.1에 포함될 예정이다. 아직 릴리즈는 되지 않았지만 util 클래스라 크게 바뀌지 않을 듯으로 보인다. 한번 알아보도록 하자.
DataSize dataSize = DataSize.of(10, DataUnit.TERABYTES);
System.out.println(dataSize);
System.out.println(dataSize.toGigaBytes());
아주 간단하다. 특정한 DataSize를 작성하면 그에 맞게 원하는 데이터 형식으로 바꿔준다. 위의 코드는 10테라
바이트를 기가 바이트로 바꾸어 리턴해주는 코드이다. 실제로 내부적으로는 long 형태의 byte 로 저장하고 있다. 지금 현제 지원해주는 단위는 BYTES
, KILOBYTES
, MEGABYTES
, GIGABYTES
, TERABYTES
를 지원해주 고 있다. 뭐 아직까지는 테라바이트 이상으로는 필요 없을 듯으로 판단하여 그런듯 하다.
위의 예제는 of
메서드를 이용해서 생성했지만 굳이 그럴 필요 없이 ofXXX
메서드를 이용해서 사용하면 더욱 편리하다.
DataSize bytes = DataSize.ofBytes(100);
DataSize kiloBytes = DataSize.ofKiloBytes(100);
DataSize megaBytes = DataSize.ofMegaBytes(100);
DataSize gigaBytes = DataSize.ofGigaBytes(100);
DataSize teraBytes = DataSize.ofTeraBytes(100);
좀 더 간편하게 사용할 수 있을 듯하다. 이것은 Spring에서 지원해주는 클래스지만 Spring boot 2.1에서도 직접적으로 사용할 수 있다.
@ConfigurationProperties("foo")
public class DataSizeProperties {
private DataSize tempSize;
public DataSize getTempSize() {
return tempSize;
}
public void setTempSize(DataSize tempSize) {
this.tempSize = tempSize;
}
}
우리가 자주 사용하는 @ConfigurationProperties
어노테이션에서도 DataSize
클래스를 사용해서 매핑할 수 있다.
사용법은 아래와 같이 간단하다.
foo.temp-size=10
foo.temp-size=10MB
foo.temp-size=10GB
...
기본적으로 아무 단위가 없다면 Byte로 설정된다. 만약 원하는 단위가 있다면 위 처럼 해당 단위를 작성해주면 된다. 하지만 여기서 주의할 점은 모두 대문자를 이용해야 한다는 것이다. 왜소문자는 파싱을 안되게 했을까? 흠흠 Enum 타입에 있는 문자로 결정하는 것 같은데 자세히는 살펴보지 않았다. 아무튼 그렇다.
만약 해당 타입을 기본적인 단위로 지정해주고 싶다면 다음과 같이작성해도 무방하다.
@ConfigurationProperties("foo")
public class DataSizeProperties {
@DataSizeUnit(DataUnit.GIGABYTES)
private DataSize tempSize;
public DataSize getTempSize() {
return tempSize;
}
public void setTempSize(DataSize tempSize) {
this.tempSize = tempSize;
}
}
위와 같이 @DataSizeUnit
어노테이션을 이용해서 해당 단위를 기본적으로 설정 할 수 있다. 그러면 프로퍼티에 굳이 해당 단위를 명시해주지 않아도 된다. 만약 명시해준다면 기본타입은 무시가 되고 작성한 타입으로 동작된다.
AnnotatedClassFinder
이 클래스는 Spring boot 2.1 에 새롭게 나타난 클래스이다. 그렇다고 해서 완전하게 새로운 클래스는 아니다.(?) 기존의 있던 SpringBootConfigurationFinder
클래스를 살짝 변경한? 클래스이다. 기존에는 @SpringBootConfiguration
어노테이션만을 파싱하기 위한 클래스라면 AnnotatedClassFinder
클래스 경우에는 원하는 어노테이션을 파싱할 수 있다.
SpringBootConfigurationFinder() {
this.scanner = new ClassPathScanningCandidateComponentProvider(false);
this.scanner.addIncludeFilter(
new AnnotationTypeFilter(SpringBootConfiguration.class));
this.scanner.setResourcePattern("*.class");
}
위의 코드는 기존의 클래스이며 아래의 코드는 새롭게 탄생한 코드이다.
public AnnotatedClassFinder(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "AnnotationType must not be null");
this.annotationType = annotationType;
this.scanner = new ClassPathScanningCandidateComponentProvider(false);
this.scanner.addIncludeFilter(new AnnotationTypeFilter(annotationType));
this.scanner.setResourcePattern("*.class");
}
차이라곤 뭐 생성자에 어노테이션을 받는 부분이 추가 된 것 뿐이다.
사용법은 해당 클래스를 보면 쉽게 알 것 같다. 그래서 생략 하겠다..
PropertyMapper
PropertyMapper
클래스는 Spring boot 2.0 에서 추가된 클래스이다.
이 클래스의 용도는 프로퍼티들을 매핑 시켜주는? 그런 역할을 하는 클래스이다. 예를들어 Spring boot 의 @ConfigurationProperties
를 사용해서 프로퍼티들을 매핑 시켰다면 그 이후에 그 프로퍼티들을 실제 사용하는 프로퍼티에 매핑을 시켜주는 그런? 클래스이다. 흠 말로는 어려우니 코드를 살펴보도록 하자.
class FooProperties {
private int timeout;
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
}
class FooTemplate {
private int timeout;
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public void bar() {
//...
//this.timeout
}
}
예를 들어 위와 같은 클래스가 있다고 가정하자. FooProperties
클래스는 클라이언트로부터 프로퍼티를 받는 클래스이고 FooTemplate
은 실제 그 프로퍼티로 어떤 작업등을 하는 클래스라고 가정해보자. 그럼 다음과 같이 사용할 수 있다.
PropertyMapper map = PropertyMapper.get();
FooProperties properties = new FooProperties();
properties.setTimeout(10);
FooTemplate fooTemplate = new FooTemplate();
map.from(properties::getTimeout).to(fooTemplate::setTimeout);
위와 같이 FooProperties
클래스로 부터 받은 프로퍼티를 FooTemplate
의 속성으로 넣는 작업이다. 실제로 FooTemplate
의 timeout 속성에는 10이라는 값이 들어가 있다.
또한 좀 더 나은 방식도 제공해준다. 예를들어 source
의 프로퍼티가 null일 경우에 굳이 target
프로퍼티에게 null을 넣을 필요가 없다면 다음과 같이 작성하면 된다.
map.from(properties::getTimeout).whenNonNull().to(fooTemplate::setTimeout);
그러면 fooTemplate 클래스에 timeout은 영향 받지 않는다. 또한 간단하게 타입도 변경할 수 있다. 예를들어 FooTemplate
의 timeout의 속성이 String이라면 다음과 같이 타입도 변경할 수 있다.
map.from(properties::getTimeout).as(String::valueOf).to(fooTemplate::setTimeout);
필자가 말한 위의 메서드뿐만아니라 많은 메서드가 존재하니 필요하다면 한번씩 살펴보는 것도 나쁘지 않다.
TestPropertyValues
이 클래스는 Spring boot 2.0에 새로생긴 클래스 이다. 하지만 우리가 딱히 직접적으로 사용할 클래스는 아니다. 기존의 존재했던 클래스 (EnvironmentTestUtils) 클래스가 Deprecated 되고 해당 클래스가 생겼다.
예전에 Test 할 때 주로 EnvironmentTestUtils.addEnvironment 메서드를 사용했지만 이제는 TestPropertyValues를 사용하면 되는데 해당 클래스를 직접적으로 사용할 일은 없다. 뭐 있을 수는 있겠지만 딱히 커스텀하게 만들지 않는 이상은..
왜냐하면 기존의 Config를 테스트 하던 클래스가 Spring boot 2.0 부터 새롭게 바뀌면서 ApplicationContextRunner
를 이용하면 되기 때문이다.
예전에 RC 버전일때 포스팅한 내용은 여기있다. 궁금하다면 참고하면 되겠다.
여기에 존재하는 withPropertyValues
가 내부적으로 바로 TestPropertyValues 이다. 하지만 우리는 그냥 String 타입으로 넘겨서 알아채지 못했을 수도 있다.
private final TestPropertyValues environmentProperties;
//...
public SELF withPropertyValues(String... pairs) {
return newInstance(this.contextFactory, this.initializers,
this.environmentProperties.and(pairs), this.systemProperties,
this.classLoader, this.parent, this.configurations);
}
딱히 사용할일은 없지만 그래도 이런게 있다고는 알아봤다. 오늘 내용은 Spring 의 새로운 클래스들을 몇개 알아봤다. 물론 다 알아 보고 싶지만 그러지 못한다. 깊은 내용의 클래스들도 있고 뭐가 뭔지 모르는 클래스도 있고 아직 확인 못한 클래스도 있으니.. 오늘은 여기까지만 알아보도록 하자. 추후에 더 알아 볼 수 있으면 알아보도록 하자.
유틸성 클래스들이라 해당 클래스 직접사용해봐도 쉽게 이해할 수 있을 것으로 판단 된다.
그럼 오늘은 이만!