Clean Code that Works.

Java 8 부터 interface에도 body를 가진 Default Methods 를 지원.

 

import java.time.*; 
 
public interface TimeClient {
    void setTime(int hour, int minute, int second);
    void setDate(int day, int month, int year);
    void setDateAndTime(int day, int month, int year,
                               int hour, int minute, int second);
    LocalDateTime getLocalDateTime();
    default ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }
}

위 getZonedDateTime 처럼 interface를 구현한 클래스들에서 쉽게 사용할 수 있는 유틸성 메소드다.

그 전에는 이런 유틸성 메서드들은 따로 유틸리티 클래스를 만들어서 쓰던가, 인터페이스를 구현한 추상 클래스에 넣어서 쓰던지 하는 방법을 써야됬다.

 

아무는 Default Method 쓰면 좀 편해지는 부분이 있다.

 

하지만 Kotlin 에서 Default Method를 지원하지 않는다. 

@JvmDefault 라는 Annotation 을 통해 지원하긴 한데, 컴파일 옵션 추가가 필요하고, 아직 실험적인 단계의 메서드다.

기존 코드를 변경하는 경우에는 @JvmDefault 를 사용하고 하거나 companion object 로 사용하는 방법이 있다.

interface TimeClient {
	fun setTime(hour: Int, minute: Int, second: Int)

	companion object {

		fun getZonedDateTime(zoneString: String): ZonedDateTime {
			return ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(zoneString));
		}
	}
}

 

아에 Kotlin 으로 작업할 경우에는 Default Method와 비슷하게 funtion body 를 작성해주면 된다.

 

interface TimeClient {
	fun setTime(hour: Int, minute: Int, second: Int)
	
	fun getZonedDateTime(zoneString: String): ZonedDateTime {
		return ZonedDateTime.of(LocalDateTime.now(), ZoneId.of(zoneString));
	}
}

class TimeChecker: TimeClient {
	override fun setTime(hour: Int, minute: Int, second: Int) {
		TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
	}

}

Comment +0

공식 문서가 굉장히 잘 되어 있다.

스프링 문서도 잘 되있음!

 

공식 문서 : https://kotlinlang.org/docs/reference/

 

Reference - Kotlin Programming Language

 

kotlinlang.org

Spring Kotlin 문서 : https://docs.spring.io/spring/docs/current/spring-framework-reference/languages.html#kotlin-resources

 

Language Support

Spring provides comprehensive support for using classes and objects that have been defined by using a dynamic language (such as Groovy) with Spring. This support lets you write any number of classes in a supported dynamic language and have the Spring conta

docs.spring.io

Lombok 사용 중 일경우 참고 : https://dzone.com/articles/migrating-from-lombok-to-kotlin

Lombok 으로 작성된 코드를 Kotlin 코드에서 접근할 수 없다. 

Lombok은 컴파일 시 Annotation Processor 에 의해 동작하는데 Kotlin 컴파일시 Annotaion Processor 를 사용하지 않는다.

 

 

Migrating From Lombok to Kotlin - DZone Java

There are a lot of benefits to migrating from Lombok to Kotlin, including reduced verbosity, shorter code, and improved readability.

dzone.com

Spring one 에서 발표된 Kotlin 관련 영상 : https://www.youtube.com/results?search_query=spring+one+kotlin

 

spring one kotlin - YouTube

 

www.youtube.com

 

Comment +0

한 2년전에 패치 됬던가.. 

노트패드에도 있었던 멀티 라인 선택 기능..

 

가끔씩 여러라인 한번에 고칠 필요가 있는데..이때 유용.

 

Intellij 공식 용어는 Multicursor 인듯.

https://www.jetbrains.com/help/rider/Multicursor.html

 

Multicursor - Help | JetBrains Rider

Multicursor JetBrains Rider supports multiple carets. The majority of the editor actions, such as keyboard navigation or text insertion and deletion, apply to each caret. Live templates and auto-completion are supported as well. It is possible to add or de

www.jetbrains.com

Shift+Alt+Insert 로 활성화 후에 선택하고. 한번더 선택 하면 Multicursor 모드 해제 됨.

 

Comment +0

정말 처음 봤던 내용.

=======================================================================================================================

Spring에서는 비동기 처리 및 스케쥴링 처리를 위해서 @Async, @Scheduled 를 지원하는데요.
아래처럼 간단한 설정으로 사용 하기도 합니다.

<task:annotation-driven />

위 설정으로 세팅하고 @Scheduled를 사용하는데, 사용하는 입장에서는 당연히 비동기로 동작할 것이라 생각합니다.
(특정 시간에 동작하도록 하거나, fixedDelpay를 사용할 때)

하지만! 아무 설정을 하지 않을 경우에는 실제 작업을 수행하는 bean이 ConcurrentTaskScheduler로 설정되어 concurrent 하게 수행됩니다!

해서 비동기로 수행하고 싶으면 아래 처럼 설정을 추가해주시면 됩니다.

<bean class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
    <property name="poolSize" value="10"/>
</bean>
// or
<task:scheduler id="scheduler" pool-size="10" />

그럼 비동기로 동작하는 것을 확인 할 수 있습니다.

참고로 디폴트로 ConcurrentTaskScheduler를 등록해 주는 부분은
ScheduledAnnotationBeanPostProcessor.onApplicationEvent 에서 맨 마지막에 this.registrar.afterPropertiesSet() 를 호출해주는데
여기 들어가 보면 taskScheduler 가 null 일때 ConcurrentTaskScheduler로 세팅해주는것을 확인할 수 있습니다.

public void afterPropertiesSet() {
        if (this.taskScheduler == null) {
            this.localExecutor = Executors.newSingleThreadScheduledExecutor();
            this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
        }
        if (this.triggerTasks != null) {
            for (Map.Entry<Runnable, Trigger> entry : this.triggerTasks.entrySet()) {
                this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), entry.getValue()));
            }
        }
        if (this.cronTasks != null) {
            for (Map.Entry<Runnable, String> entry : this.cronTasks.entrySet()) {
                this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), new CronTrigger(entry.getValue())));
            }
        }
        if (this.fixedRateTasks != null) {
            for (Map.Entry<Runnable, Long> entry : this.fixedRateTasks.entrySet()) {
                this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(entry.getKey(), entry.getValue()));
            }
        }
        if (this.fixedDelayTasks != null) {
            for (Map.Entry<Runnable, Long> entry : this.fixedDelayTasks.entrySet()) {
                this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(entry.getKey(), entry.getValue()));
            }
        }
    }

감사합니다. :)

Comment +0