2024. 10. 18. 16:26ㆍSpring Boot/Spring Boot Auto Configuration
📌 DefaultListableBeanFactory 완벽 정리 🚀
DefaultListableBeanFactory
는 Spring 프레임워크에서 가장 핵심적인 BeanFactory 구현체로, 스프링 컨테이너에서 빈(Bean)의 등록, 검색, 생성, 관리 및 의존성 주입을 담당하는 클래스입니다.
ApplicationContext 내부에서 빈 팩토리를 관리하는 핵심 구성 요소로 동작하며, BeanDefinitionRegistry
, ListableBeanFactory
, AutowireCapableBeanFactory
등의 기능을 모두 포함하고 있습니다.
📌 1️⃣ DefaultListableBeanFactory 개요
✅ Spring의 기본 빈 팩토리 구현체로 BeanFactory
의 기능을 확장
✅ ApplicationContext
내부에서 사용되어 빈 정의 등록, 생성, 검색, 의존성 주입을 담당
✅ ListableBeanFactory
구현으로 모든 빈을 조회할 수 있는 기능 제공
✅ BeanDefinitionRegistry
구현으로 동적으로 빈 정의 등록 및 제거 가능
✅ AutowireCapableBeanFactory
구현으로 자동 의존성 주입(Auto-Wiring) 지원
✅ Scope(싱글톤 및 프로토타입 빈 등등) 관리 및 라이프사이클 처리 지원
📌 2️⃣ DefaultListableBeanFactory의 계층 구조
📌 DefaultListableBeanFactory
는 Spring 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 빈 정의 등록 및 관리
DefaultListableBeanFactory
는 BeanDefinitionRegistry
인터페이스를 구현하여 빈 정의(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
→ 빈 생성 후 로직 추가 가능BeanFactoryPostProcessor
→ 빈 정의 수정 가능SmartInitializingSingleton
→ 초기화 후 로직 실행
📌 BeanPostProcessor 예제
beanFactory.addBeanPostProcessor(new CustomBeanPostProcessor());
✔ 빈 초기화 전후에 추가 작업 가능
📌 7️⃣ Summary
✅ DefaultListableBeanFactory
는 스프링에서 가장 강력한 빈 팩토리 구현체
✅ 빈 정의 등록, 검색, 생성, 의존성 주입, 라이프사이클 관리 기능 제공
✅ ApplicationContext
내부에서 사용되며 스프링 컨테이너의 핵심 역할 수행
✅ 확장성이 뛰어나 BeanPostProcessor
및 BeanFactoryPostProcessor
활용 가능
🚀 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: 사용자 정보를 가져옵니다.
🔍 정리
- DefaultListableBeanFactory 사용
- registerBeanDefinition()을 통해 빈을 등록하고 관리.
- getBean()을 통해 빈을 가져와 사용.
- BeanPostProcessor 활용
- 빈의 초기화 전후에 특정 로직을 수행할 수 있도록 처리.
- BeanFactoryPostProcessor 활용
- 빈 정의를 조작하여 Lazy Initialization 등의 설정 변경 가능.
- 자동 주입이 적용되지 않음
- DefaultListableBeanFactory는 ApplicationContext와 다르게 자동 의존성 주입을 지원하지 않으므로, orderService에 userService를 수동으로 주입해야 함.
📌 결론
실제 프로젝트에서는 ApplicationContext를 주로 사용하지만,
DefaultListableBeanFactory는 커스텀 컨테이너를 만들거나 동적으로 빈을 등록/조작해야 할 때 유용합니다.
특히, BeanPostProcessor와 BeanFactoryPostProcessor를 통해 빈의 생성과 초기화를 커스텀할 수 있습니다.
'Spring Boot > Spring Boot Auto Configuration' 카테고리의 다른 글
Spring Boot Auto-Configuration (0) | 2024.10.18 |
---|---|
ConfigurationClassPostProcessor (1) | 2024.10.18 |
ConfigurationClassParser (0) | 2024.10.18 |
PostProcessorRegistrationDelegate (0) | 2024.10.18 |
AnnotationConfigServletWebServerApplicationContext (0) | 2024.10.18 |