@PostConstruct 어노테이션

@PostConstruct 는 의존성 주입(쉽게 말해 Autowired)이 이루어진 후 초기화를 수행하는 메서드 어노테이션이다. @PostConstruct가 붙은 메서드는 프레임워크에 의해 Bean 에 등록된 후 수행된다.
이 메서드는 다른 리소스에 의해 호출되지 않는다해도 수행된다.

  • 해당 Bean 의 초기화 작업에 의존성이 있는 다른 Bean 의 리소스가 필요한 경우(ex.DB 조회를 통한 데이터 초기화)
  • 서비스 실행 시 단 1회 실행됨을 보장하기 위한 경우

@PreDestroy 어노테이션

@PreDestroy 어노테이션은 @PostConstruct 와 비슷한 맥락으로, Bean 의 마지막 소멸 단계에서 Bean 을 제거하기 전에 처리해야 할 작업이 있는 경우 수행하는 메서드 어노테이션이다.


테스트

서비스 실행 시, DB에서 게시판의 카테고리 리스트 데이터를 조회하여 필드에 저장하고, Bean 소멸 시 이 필드값을 소멸시키는 테스트를 진행해 보자.

  • board.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="board">

	<select id="getBoardCategories" resultType="BoardCategoryVO">
		SELECT cat_id as catId
			cat_nm as catNm
		FROM board_category
		WHERE use_yn = 'Y'
		ORDER BY sort ASC
	</select>		
</mapper>
  • BoardDao.java
@Repository
public class BoardDao {
	
	@Autowired
	@Qualifier("sqlSessionTemplate")
	protected SqlSession sqlSession;
	
	public List<BoardCategoryVO> getBoardCategories() throws Exception {
		System.out.println("run BoardDao::getBoardCategories()");
		return this.sqlSession.selectList("board.getBoardCategories");
	}
}
  • BoardService.java
@Service
public class BoardService {

	@Autowired
	private BoardDao boardDao;

	private final List<BoardCategoryVO> categories = null;

	// Bean 생성 > 의존성 주입 > @PostConstruct 실행
	@PostConstruct
	public void init() throws Exception {
		System.out.println("run BoardService::init()");
		categories = this.boardDao.getBoardCategories(); // 의존성이 있는 다른 Bean 의 리소스를 사용할 수 있음
	}

	// @PreDestroy 실행 > Bean 제거
	@PreDestroy
	public void detsroy() throws Exception {
		System.out.println("run BoardService::destroy()");
		categories = null;
	}

	public List<BoardCategoryVO> getCategories() throws Exception {
		return this.categories;
	}
}
  • SampleApplicationTests.java
@SpringBootTest
class SampleApplicationTests {
	
	@Autowired
	private BoardService boardService;

	@Test
	void contextLoads() throws Exception {

		List<BoardCategoryVO> categories = this.boardService.getCategories();
		System.out.println(categories.toString());
	}
}

테스트 실행 시, 별도의 호출이 없더라도 @PostConstruct 의 메서드가 실행되어, DB 조회와 콘솔이 찍히는 부분을 확인 할 수 있으며, 반대로 서비스 종료 시 @PreDestroy 의 메서드가 수행되는 부분을 확인할 수 있다. 서비스 실행 도중 변동이 없음이 보장되는 DB 데이터나 External API 데이터 같은 경우 위와 같이 서비스 실행 시에 일회성으로 데이터를 조회하여 서비스 전체의 성능을 향상 시키는 방법을 도모할 수 있다.
(Caching 개념으로 사용할 수 있으나, 남발하는 건 역시 좋지 않다.)


XML 으로 Bean 을 관리하는 경우

어노테이션을 사용하지 않고 XML 으로 Bean 을 관리하는 경우 아래와 같이 할 수 있다.

<!-- ... -->

<!-- init-method, destroy-method 에 로직 상에 존재하는 메서드명을 작성 -->
<bean id="boardService"
	class="com.quicksample.nexon.board.service.BoardService"
	init-method="init"
	destroy-method="destroy">
</bean>

<!-- ... -->