Spring Container (2) - BeanFactory

Song_MinGyu·2025년 9월 16일

Spring-Framework

목록 보기
2/4
post-thumbnail

BeanFactory?

BeanFactory는 Spring IoC Container의 루트 인터페이스이다.
이 인터페이스는 Spring Bean을 생성하고, Dependency를 주입하며, 생명주기를 관리한다.

Spring Framework Github에 저장된 BeanFactory 주석을 번역하면 아래와 같다.

...
 * <p>이 인터페이스는 여러 개의 빈 정의(bean definition)를 보관하는 객체가 구현한다.
 * 각각의 빈 정의는 고유한 문자열 이름으로 식별된다. 빈 정의에 따라 팩토리는
 * 독립적인 객체 인스턴스(Prototype 패턴)나 공유되는 단일 인스턴스(팩토리 범위 내에서의 Singleton 패턴,
 * 전통적인 싱글톤 디자인 패턴보다 우월한 대안)를 반환할 수 있다.
 * 어떤 인스턴스를 반환할지는 빈 팩토리 설정에 달려 있으며, API 자체는 동일하다.
 * Spring 2.0부터는 구체적인 애플리케이션 컨텍스트에 따라 더 많은 스코프가 제공된다
 * (예: 웹 환경에서 "request" 스코프와 "session" 스코프).
 *
 * <p>이 접근 방식의 핵심은 BeanFactory가 애플리케이션 컴포넌트의 중앙 레지스트리이며,
 * 애플리케이션 컴포넌트의 설정을 중앙화한다는 점이다
 * (더 이상 개별 객체가 직접 프로퍼티 파일을 읽을 필요가 없음).
 * 이 접근의 장점에 대한 논의는 "Expert One-on-One J2EE Design and Development"
 * 4장과 11장에서 확인할 수 있다.
 *
 * <p>일반적으로는 setter나 생성자를 통한 의존성 주입(Dependency Injection, "push" 설정)을
 * 사용해서 애플리케이션 객체를 구성하는 것이, BeanFactory lookup 같은
 * "pull" 설정 방식보다 더 낫다. Spring의 의존성 주입 기능은
 * 이 BeanFactory 인터페이스와 그 하위 인터페이스를 사용하여 구현된다.
...

주석에서도 BeanFactory가 Prototype 패턴이나 Singleton 패턴을 대신 할 수 있는 구조를 제공한다.
따라서 개발자가 직접 개발하지 않아도 Spring BeanFactory가 그 역할을 수행한다.

또한 BeanFactory는 애플리케이션 컴포넌트의 중앙 레지스트리이다.
과거에는 객체마다 직접 properties 파일을 읽어 설정을 가져왔지만, 이제는 BeanFactory가 모든 설정을 중앙에서 관리한다.
BeanFactory로 객체는 오직 자신의 로직에만 집중할 수 있게 되었다.

BeanFactory 주요 기능

가장 대표적인 기능은 Bean을 조회하는 것이다.

//beans.xml 파일에 있는 bean 컨테이너에 load
BeanFactory factory = new ClasspathXmlApplicationContext("beans.xml");
//컨테이너에 올라간 Bean 호출
MyService service = factory.getBean("myService",MyService.class);

BeanFactory는 Scope 관리 기능도 제공한다.
isSingleton, isPrototype메소드를 통해 Bean이 항상 같은 인스턴스인지, 새로운 객체를 생성하는지 확인 가능하다.
웹 환경에서는 request,session까지 지원한다.

BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");

// isSingleton?
boolean single = factory.isSingleton("myService");
System.out.println("myService는 singleton인가? " + single);

// isPrototype?
boolean proto = factory.isPrototype("tempBean");
System.out.println("tempBean은 prototype인가? " + proto);

그 외에도 Bean의 타입을 확인하는 기능(isTypeMatch), Bean의 별칭을 관리하는 기능(getAliases), 그리고 FactoryBean을 구분하기 위한 접두사&기능을 제공한다.

boolean match = factory.isTypeMatch("myService", MyService.class);
System.out.println("myService의 타입이 MyService인가? " + match);

String[] aliases = factory.getAliases("myService");
System.out.println("myService의 별칭들: " + Arrays.toString(aliases));

Object factoryBean = factory.getBean("&myFactoryBean"); // FactoryBean 자체
Object productBean = factory.getBean("myFactoryBean");  // FactoryBean이 생성한 객체

BeanFactory의 확장 인터페이스

BeanFactory는 뼈대 역할을 한다. 실제 애플리케이션에서 우리가 사용하는 강력한 기능들은 모두 확장 인터페이스를 통해 제공된다.

  • ListableBeanFactory: 여러 개의 Bean을 한 번에 조회할 수 있다.
  • HierarchicalBeanFactory: 부모-자식 컨텍스트 구조를 지원한다.
  • AutowireCapableBeanFactory: 의존성 자동 주입과 BeanPostProcessor 적용을 지원한다.
  • ConfigurableBeanFactory: 스코프와 Bean 후처리기 등록 등 고급 설정을 제공한다.

이러한 확장을 모두 구현한 대표 클래스가 DefaultListableBeanFactory
Spring 내부에서 Bean 관리의 핵심적인 역할을 수행하는 클래스이다.
ApplicationContext도 결국 내부적으로 DefaultListableBeanFactory를 사용.

Bean의 생명주기

BeanFactory는 단순히 Bean을 생성하는 역할에 그치지 않는다.
Bean의 초기화부터 소멸까지 전 과정을 관리한다.

초기화 과정

  1. setBeanName, setBeanFactory 등의 Aware 인터페이스 호출
  2. BeanPostProcessorpostProcessBeforeInitialization 실행
  3. afterPropertiesSet() 호출 또는 사용자가 정의한 init-method 실행
  4. BeanPostProcessorpostProcessAfterInitialization 실행

소멸 과정

  1. DestructionAwareBeanPostProcessorpostProcessBeforeDestruction 실행
  2. destroy() 호출
  3. 사용자가 정의한 destroy-method 실행

이러한 생명주기 과정을 이해하면 왜 @PostConstruct와 @PreDestroy가 중요한지 알 수 있다.
또한 BeanPostProcessor가 단순한 후처리를 넘어서, Spring AOP나 Proxy 기능을 가능하게 하는 중요한 기제라는 점도 이해할 수 있다.

정리

실제로 BeanFactory는 직접적으로 다루는 일이 거의 없다고 생각한다.
하지만 Spring의 모든 컨테이너는 BeanFactory 기반으로 동작한다.

Spring의 동작 구조를 정확하게 이해하기 위해서는 Spring Container를 이해하는 것이 필요하고,
Spring Container를 이해하기 위해서는 BeanFactory를 이해하는 것이 중요하다.

profile
Always try to Change and Keep this mind

0개의 댓글