본문 바로가기
Java

Try-with-resources를 이용한 자원 해제 처리

by parkjp 2023. 8. 19.

 

Try-with-resources란?

 try-catch문과는 달리 AutoCloseable 인터페이스를 구현한 객체의 자원을 try문이 끝나면 자동으로

close 처리해준다. 말로하는 것보다는 소스를 보는게 빠를 것이다.

 

 

RedisTemplate을 이용한 Try-with-resources 예제 (Examples)

 예시로 RedisTemplate의 scan을 들어보았다. 우선 일반적으로 try-catch-finally문으로 redisConnection을 close하는

방법을 살펴보자.

 

// RedisTemplate scan 예시

public void scan(String pattern) {
    ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(100).build();
    RedisConnection redisConnection = null;
    
    try {
        redisConnection = Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection();
        RedisKeyCommands keyCommands = redisConnection.keyCommands();
        Cursor<byte[]> cursor = keyCommands.scan(scanOptions);
        
        while(cursor.hasNext()) {
        	// do something
        }
    } catch(Exception e) {
    	// do something
    } finally {
    	if(redisConnection != null) {
           redisConnection.close();
        }
    }
}

 

일부러 connectionFactory에서 getConnection을 가져와서 scan함수를 써보았다.

여기서 RedisConnection 객체는 AutoCloseable 인터페이스를 구현하고 있고,

또한 scan함수가 리턴하는 Cursor객체도 마찬가지로 살펴보면 CloseableIterator라는 인터페이스를 구현하고 있다.

CloseableIterator는 Closeable 인터페이스를 상속하고 있고, 이 Closeable 인터페이스가 AutoCloseable 인터페이스를 상속하고 있다.

 

따라서 RedisConnection 객체와 Cursor 객체는 AutoCloseable 인터페이스를 구현하고 있는데 이번엔 try-with-resources로 처리 하는 법을 살펴보자.

 

// RedisTemplate scan 예시

public void scan(String pattern) {
    ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(100).build();
    
    try (Cursor<byte[]> cursor = Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection().keyCommands().scan(scanOptions)) {
        while(cursor.hasNext()) {
        	// do something
        }
    } catch(Exception e) {
    	// do something
    }
}

 

위에서 언급하였듯 RedisConnection 객체와 Cursor객체는 AutoCloseable 인터페이스를 구현한 객체다. try에 해당 객체를 지정해 주면 try문이 끝나면 자동으로 redisConnection.close()가 처리되어 Connection 자원이 해제된다.

 

이번엔 keyCommand().scan()이 아닌 redisTemplate.scan()으로 처리해보자.

keyCommand()나 hashCommand()처럼 Command객체로 처리하면 Cursor<byte[]>나 Cursor<Map.Entry<byte[], byte[]>>로 리턴되지만 redisTemplate.scan()으로 처리하면 bean에 등록한 redisTemplate 타입에 따라 리턴값이 나오게 된다.

 

// RedisTemplate scan 예시

public void scan(String pattern) {
    ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(100).build();
    
    try (Cursor<String> cursor = this.redisTemplate.scan(scanOptions)) {
        while(cursor.hasNext()) {
        	// do something
        }
    } catch(Exception e) {
    	// do something
    }
}

 

 

결론

 AutoCloseable 인터페이스는 Java 1.7부터 나왔다. try-catch-finally문으로 명시적으로 close를 호출해도 좋지만

AutoCloseable 인터페이스를 쓰라고 만들어 놓았으니 적용해서 소스가 좀 더 간단해 보이도록 하는 것도 좋을 것 같다.

 

반응형