목차
FactoryBean을 사용해야 하는 경우와 사용 예제
Spring의 FactoryBean 사용 사례를 다룬 외부 글을 찾기 위한 링크 메모다. 링크가 열리지 않으면 제목의 FactoryBean을 기준으로 Spring 공식 문서를 찾아보면 된다.
FactoryBean<T>은 빈 자체가 아니라 그 빈이 만들어 주는 객체를 컨테이너에 노출할 때 사용한다. 생성 과정이 복잡하거나 외부 라이브러리 객체의 생성 방식을 감싸야 할 때 검토할 수 있다. 보통의 애플리케이션 객체라면 생성자나 @Bean 메서드만으로 충분한지 먼저 확인한다. 위 링크의 구체적인 예제 코드는 이 메모에 보관되어 있지 않다.
일반 @Bean: 설정 메서드 → 객체 생성 → 컨테이너 등록
FactoryBean: 팩터리 빈 등록 → getObject() → 생성된 객체 사용
팩터리 자체와 팩터리가 만든 객체를 구분하는 것이 핵심이다. 빈 이름으로 조회하면 일반적으로 만들어진 객체를 받고, 팩터리 자체가 필요할 때는 & 접두사를 붙여 조회한다. 생성 시점과 객체의 재사용 여부는 FactoryBean 구현과 빈 스코프 설정을 함께 확인한다.
실제 예: MyBatis의 SqlSessionFactoryBean
MyBatis-Spring은 SqlSessionFactoryBean을 제공한다. 컨테이너에 등록하는 객체는 팩터리지만, 다른 빈이 주입받는 것은 팩터리가 생성한 SqlSessionFactory다. 기존 MyBatis 설정을 Spring 빈 생성 과정에 연결해야 하는 사례라 FactoryBean의 목적이 잘 드러난다.
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
여기서 dataSource는 별도로 구성한 DB 연결 풀 빈이다. getBean("sqlSessionFactory")는 완성된 SqlSessionFactory를, getBean("&sqlSessionFactory")는 SqlSessionFactoryBean을 조회한다. &를 붙여야 하는 이유는 같은 빈 이름이 평소에는 생산물의 이름으로 취급되기 때문이다. MyBatis-Spring 공식 설정 예제에서도 이 구조를 사용한다.
flowchart LR C["Spring 컨테이너"] --> F["SqlSessionFactoryBean"] D["DataSource"] --> F F --> P["SqlSessionFactory"] P --> M["Mapper / 서비스"]
그림에서 DataSource는 팩터리의 입력이고 SqlSessionFactory는 생산물이다. Mapper를 사용하는 서비스는 팩터리 구현을 알 필요가 없다. 반대로 팩터리 자체를 검사하거나 설정해야 하는 코드는 & 접두사로 팩터리를 명시적으로 조회한다.
직접 만들기 전에 결정할 것
외부 라이브러리 생성자가 여러 단계의 설정과 초기화를 요구해 컨테이너의 일반 @Bean 메서드로 설명하기 어렵다면 FactoryBean<T>을 검토할 수 있다. 구현 시 getObject()의 실패를 숨기지 말고, getObjectType()에 가능한 한 정확한 타입을 반환해야 자동 주입 시 타입을 찾을 수 있다. isSingleton()과 실제 객체 재사용 방식이 다르면 요청마다 객체가 새로 생기거나 공유되리라 기대한 상태가 꼬인다.
단순한 객체 하나를 만드는 코드라면 @Configuration의 @Bean 메서드가 생성 과정과 의존성을 더 쉽게 보여준다. 도입 기준은 팩터리라는 이름의 패턴을 쓰고 싶은지가 아니라, 컨테이너에 생산물을 빈으로 노출해야 하는가다. 빈 조회 실패가 나면 먼저 팩터리 빈 등록 여부, getObjectType(), getObject() 예외, 주입 대상 타입을 차례로 본다.
참고: Spring 컨테이너 확장점: FactoryBean, MyBatis-Spring SqlSessionFactoryBean.