DefaultListableBeanFactory

2024. 10. 18. 16:26Spring Boot/Spring Boot Auto Configuration

📌 DefaultListableBeanFactory 완벽 정리 🚀

DefaultListableBeanFactorySpring 프레임워크에서 가장 핵심적인 BeanFactory 구현체로, 스프링 컨테이너에서 빈(Bean)의 등록, 검색, 생성, 관리 및 의존성 주입을 담당하는 클래스입니다.
ApplicationContext 내부에서 빈 팩토리를 관리하는 핵심 구성 요소로 동작하며, BeanDefinitionRegistry, ListableBeanFactory, AutowireCapableBeanFactory 등의 기능을 모두 포함하고 있습니다.

📌 1️⃣ DefaultListableBeanFactory 개요

Spring의 기본 빈 팩토리 구현체BeanFactory의 기능을 확장
ApplicationContext 내부에서 사용되어 빈 정의 등록, 생성, 검색, 의존성 주입을 담당
ListableBeanFactory 구현으로 모든 빈을 조회할 수 있는 기능 제공
BeanDefinitionRegistry 구현으로 동적으로 빈 정의 등록 및 제거 가능
AutowireCapableBeanFactory 구현으로 자동 의존성 주입(Auto-Wiring) 지원
Scope(싱글톤 및 프로토타입 빈 등등) 관리라이프사이클 처리 지원

📌 2️⃣ DefaultListableBeanFactory의 계층 구조

📌 DefaultListableBeanFactorySpring BeanFactory의 가장 구체적인 구현체로,
아래와 같은 계층 구조를 가집니다.

java.lang.Object
 └── org.springframework.core.SimpleAliasRegistry
      └── org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
           └── org.springframework.beans.factory.support.FactoryBeanRegistrySupport
                └── org.springframework.beans.factory.support.AbstractBeanFactory
                     └── org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
                          └── org.springframework.beans.factory.support.DefaultListableBeanFactory

 

📌 구현된 주요 인터페이스
DefaultListableBeanFactory는 여러 개의 인터페이스를 구현하여 강력한 기능을 제공합니다.

인터페이스 설명
BeanFactory 기본적인 빈 관리 기능 제공 (빈 생성 및 검색)
ConfigurableBeanFactory 빈 팩토리의 설정 관리 (스코프, 부모 팩토리 등)
ListableBeanFactory 등록된 모든 빈 조회 가능
AutowireCapableBeanFactory 자동 의존성 주입(Auto-Wiring) 지원
ConfigurableListableBeanFactory 빈 팩토리의 확장 및 커스터마이징 가능
SingletonBeanRegistry 싱글톤 빈 관리
BeanDefinitionRegistry BeanDefinition 등록 및 관리
AliasRegistry 빈의 별칭(alias) 관리

📌 3️⃣ 주요 기능

✅ 3.1 빈 정의 등록 및 관리

DefaultListableBeanFactoryBeanDefinitionRegistry 인터페이스를 구현하여 빈 정의(BeanDefinition)를 등록, 수정, 삭제할 수 있습니다.

📌 빈 등록 예제

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;

public class BeanFactoryExample {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 빈 정의 생성 및 등록
        BeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClassName("com.example.MyBean");
        beanFactory.registerBeanDefinition("myBean", beanDefinition);

        // 빈 정의 확인
        System.out.println("Bean 등록 여부: " + beanFactory.containsBeanDefinition("myBean"));
    }
}

registerBeanDefinition(String name, BeanDefinition definition)
containsBeanDefinition(String name)으로 등록 여부 확인

✅ 3.2 빈 조회 및 검색

📌 빈 조회 메서드

메서드 설명
getBean(String name) 특정 이름의 빈 반환
getBeansOfType(Class<?> type) 특정 타입의 모든 빈 조회
containsBeanDefinition(String name) 빈 정의가 존재하는지 확인

 

📌 예제

// 특정 빈 조회
Object myBean = beanFactory.getBean("myBean");

// 특정 타입의 모든 빈 조회
Map<String, MyService> services = beanFactory.getBeansOfType(MyService.class);

✅ 3.3 의존성 주입 및 자동 주입

📌 AutowireCapableBeanFactory 구현으로 자동 의존성 주입(Auto-Wiring)을 지원합니다.

메서드 설명
autowireBean(Object existingBean) 기존 객체에 자동으로 빈 주입
resolveDependency(DependencyDescriptor, ...) 특정 의존성 자동 주입

📌 의존성 주입 예제

MyComponent myComponent = new MyComponent();
beanFactory.autowireBean(myComponent);

autowireBean()을 사용하면 스프링 빈 컨테이너가 의존성을 자동으로 주입

✅ 3.4 빈 스코프 및 라이프사이클 관리

📌 빈 스코프 지원

  • singleton (기본값)
  • prototype
  • request, session, application (웹 환경)

📌 싱글톤 및 프로토타입 빈 관리

beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);

SCOPE_PROTOTYPE을 설정하면 매번 새로운 객체를 생성

✅ 3.5 계층형 BeanFactory 지원

📌 DefaultListableBeanFactory부모 빈 팩토리를 설정하여 계층형 구조를 지원

beanFactory.setParentBeanFactory(parentBeanFactory);

부모 빈 팩토리에서 빈을 검색하여 재사용 가능

📌 4️⃣ DefaultListableBeanFactory의 내부 구조

📌 주요 내부 데이터 구조

필드  설명 
beanDefinitionMap  빈 이름 → BeanDefinition 매핑
singletonObjects  싱글톤 빈 인스턴스 캐시
beanDefinitionNames  등록된 모든 빈 이름 리스트
dependentBeanMap  특정 빈이 의존하는 다른 빈 목록

 

📌 Singleton 빈 저장소

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

✔ 이미 생성된 싱글톤 빈 인스턴스를 캐싱하여 성능 최적화

📌 5️⃣ 라이프사이클 (Lifecycle)

DefaultListableBeanFactory는 스프링 애플리케이션의 라이프사이클을 관리합니다.

1️⃣ 빈 정의 등록registerBeanDefinition()
2️⃣ 빈 인스턴스 생성createBean()
3️⃣ 의존성 주입populateBean()
4️⃣ 초기화 콜백 실행invokeInitMethods()
5️⃣ 사용 후 종료 처리destroySingletons()

 

📌 라이프사이클 예제

beanFactory.preInstantiateSingletons();
beanFactory.destroySingletons();

싱글톤 빈을 초기화 & 소멸 처리 가능

📌 6️⃣ DefaultListableBeanFactory의 확장성

🔍 여기를 참고하세요

 

📌 확장 가능한 인터페이스

📌 BeanPostProcessor 예제

beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor());

빈 초기화 전후에 추가 작업 가능

📌 7️⃣ Summary

DefaultListableBeanFactory스프링에서 가장 강력한 빈 팩토리 구현체
빈 정의 등록, 검색, 생성, 의존성 주입, 라이프사이클 관리 기능 제공
ApplicationContext 내부에서 사용되며 스프링 컨테이너의 핵심 역할 수행
확장성이 뛰어나 BeanPostProcessorBeanFactoryPostProcessor 활용 가능

 

🚀 Spring 내부 동작을 깊이 이해하려면 DefaultListableBeanFactory의 구조를 잘 알아두는 것이 중요합니다!


📌DefaultListableBeanFactory를 활용한 프로젝트 샘플 

이 샘플에서는 다음과 같은 기능을 포함합니다:

  • BeanDefinition을 직접 등록하여 스프링 컨테이너를 구성
  • 빈을 수동으로 조회 및 생성
  • BeanPostProcessor를 활용한 빈 후처리
  • BeanFactoryPostProcessor를 활용한 BeanDefinition 조작

📌 프로젝트 구조

/src
 ├── config
 │    ├── MyBeanFactoryPostProcessor.java
 │    ├── MyBeanPostProcessor.java
 ├── service
 │    ├── UserService.java
 │    ├── OrderService.java
 ├── MainApp.java

1️⃣ UserService (사용자 서비스)

빈으로 등록될 간단한 서비스 클래스입니다.

package service;

public class UserService {
    public void printUser() {
        System.out.println("UserService: 사용자 정보를 가져옵니다.");
    }
}

2️⃣ OrderService (주문 서비스)

빈을 등록하여 의존성 주입을 시도할 클래스입니다.

package service;

public class OrderService {
    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void processOrder() {
        System.out.println("OrderService: 주문을 처리합니다.");
        userService.printUser();
    }
}

3️⃣ MyBeanPostProcessor (빈 후처리기)

빈이 초기화되기 전후에 로직을 실행하는 BeanPostProcessor입니다.

package config;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("🛠 [BeanPostProcessor] 빈 초기화 전: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("✅ [BeanPostProcessor] 빈 초기화 후: " + beanName);
        return bean;
    }
}

4️⃣ MyBeanFactoryPostProcessor (BeanDefinition 조작기)

빈 정의를 조작하는 BeanFactoryPostProcessor입니다.

package config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("⚙️ [BeanFactoryPostProcessor] 빈 팩토리 후처리 실행");

        // 특정 빈 정의 수정
        if (beanFactory.containsBeanDefinition("userService")) {
            BeanDefinition userServiceDefinition = beanFactory.getBeanDefinition("userService");
            userServiceDefinition.setLazyInit(true);  // Lazy Initialization 설정
            System.out.println("🚀 [BeanFactoryPostProcessor] userService를 LazyInit으로 변경");
        }
    }
}

5️⃣ MainApp (DefaultListableBeanFactory 직접 사용)

이제 DefaultListableBeanFactory를 활용하여 직접 빈을 등록하고 관리하는 코드를 작성합니다.

package main;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import config.MyBeanPostProcessor;
import config.MyBeanFactoryPostProcessor;
import service.UserService;
import service.OrderService;

public class MainApp {
    public static void main(String[] args) {
        // 🌱 DefaultListableBeanFactory 생성
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 🏗 BeanDefinition 등록
        GenericBeanDefinition userServiceDefinition = new GenericBeanDefinition();
        userServiceDefinition.setBeanClass(UserService.class);
        beanFactory.registerBeanDefinition("userService", userServiceDefinition);

        GenericBeanDefinition orderServiceDefinition = new GenericBeanDefinition();
        orderServiceDefinition.setBeanClass(OrderService.class);
        orderServiceDefinition.setAutowireCandidate(true);  // 자동 주입 대상
        beanFactory.registerBeanDefinition("orderService", orderServiceDefinition);

        // 🛠 BeanFactoryPostProcessor 적용 (BeanDefinition 변경)
        MyBeanFactoryPostProcessor factoryPostProcessor = new MyBeanFactoryPostProcessor();
        factoryPostProcessor.postProcessBeanFactory(beanFactory);

        // 🎛 BeanPostProcessor 추가 (빈 후처리)
        beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());

        // 🏭 빈 생성 및 의존성 주입 (명시적 호출 필요)
        UserService userService = (UserService) beanFactory.getBean("userService");
        OrderService orderService = (OrderService) beanFactory.getBean("orderService");

        // ❗ OrderService에 UserService 수동 주입 (자동 주입 X)
        orderService.setUserService(userService);

        // 🚀 서비스 실행
        orderService.processOrder();
    }
}

📌 실행 결과

⚙️ [BeanFactoryPostProcessor] 빈 팩토리 후처리 실행
🚀 [BeanFactoryPostProcessor] userService를 LazyInit으로 변경
🛠 [BeanPostProcessor] 빈 초기화 전: userService
✅ [BeanPostProcessor] 빈 초기화 후: userService
🛠 [BeanPostProcessor] 빈 초기화 전: orderService
✅ [BeanPostProcessor] 빈 초기화 후: orderService
OrderService: 주문을 처리합니다.
UserService: 사용자 정보를 가져옵니다.

🔍 정리

  1. DefaultListableBeanFactory 사용
    • registerBeanDefinition()을 통해 빈을 등록하고 관리.
    • getBean()을 통해 빈을 가져와 사용.
  2. BeanPostProcessor 활용
    • 빈의 초기화 전후에 특정 로직을 수행할 수 있도록 처리.
  3. BeanFactoryPostProcessor 활용
    • 빈 정의를 조작하여 Lazy Initialization 등의 설정 변경 가능.
  4. 자동 주입이 적용되지 않음
    • DefaultListableBeanFactory는 ApplicationContext와 다르게 자동 의존성 주입을 지원하지 않으므로, orderService에 userService를 수동으로 주입해야 함.

📌 결론

실제 프로젝트에서는 ApplicationContext를 주로 사용하지만,
DefaultListableBeanFactory는 커스텀 컨테이너를 만들거나 동적으로 빈을 등록/조작해야 할 때 유용합니다.
특히, BeanPostProcessor와 BeanFactoryPostProcessor를 통해 빈의 생성과 초기화를 커스텀할 수 있습니다.