본문 바로가기
Programming/Analyze Open Source

[Spring -Beans] BeanFactory Interface #1

by TinKerBellBass 2022. 4. 17.
728x90
반응형

아래 공식문서를 순서대로 읽으며 천천히 여유 있게 소스 분석을 해보려고 한다.

 

Spring Framework Documentation

Overview history, design philosophy, feedback, getting started. Core IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP. Testing Mock Objects, TestContext Framework, Spring MVC Test, WebTestClient. Data Access Tran

docs.spring.io

Overview 는 넘어가고 Core 부터 시작한다.

제일 처음 나오는 The IoC Container 에서 다음과 같이  

BeanFactory 와 그 서브 인터페이인 ApplicationContext 인터페이스를 소개하고 있다.

영어 울렁울렁.. 영어 공부도 되겠구나. 

영어는 구글 번역에 의존하는 경우가 많기 때문에 틀린 내용이 많이 있을 거라 예상된다.

그리고 코드의 세세한 분석보다는 OOP 관점에서 분석하려고 한다.

 

"The org.springframework.beans and org.springframework.context packages are the basis for Spring Framework’s IoC container. The BeanFactory interface provides an advanced configuration mechanism capable of managing any type of object. ApplicationContext is a sub-interface of BeanFactory. It adds:"

 

그럼 첫 대상은 BeanFactory 로 결정!

 

BeanFactory Interface

BeanFactory 인터페이스에는 정의되어 있는 필드 및 메서드는 API 문서에 자세히 나와있다.

팩토리에서 반환되는 인스턴스와 팩토리 인스턴스를 구분하기 위한 상수 하나가 정의되어 있고

빈들의 상태와 값을 조회하는 메소드로 이루어져 있다.

각 메서드의 자세한 스펙은 API 문서에서 확인할 수 있다.

 

BeanFactory (Spring Framework 5.3.19 API)

Determine the type of the bean with the given name. More specifically, determine the type of object that getBean(java.lang.String) would return for the given name. For a FactoryBean, return the type of object that the FactoryBean creates, as exposed by Fac

docs.spring.io

 

 

BeanFactory Interface implements 하는 인터페이스와 클래스

인텔리제이에서 BeanFactory Interface 에 대고 Go To Implementation(s) 를 해보면..

45 개의 인터페이스와 클래스들이 구현에 참여하고 있다. BeanFactory 녀석 인기 좋구나. 

알파벳 순으로 정렬되기 때문에 첫 줄에 친숙한 AbstractApplicationContext 가 표시되기는 한다.

 

 

이 모든 인터페이스와 클래스를 다 살펴보기는 힘들것 같아서

진짜 getBean 메서드를 구현하고 있는 클래스를 찾아보았다.

다섯 개의 클래스가 검색되는데 마지막의 테스트를 위한 스텁은 제외한 네 개의 클래스를 살펴보자.

역시 스프링인가 Impl 이란 단어가 안 보여서 기분이 좋다.

 

AbstractApplicationContext 추상 클래스

직접 BeanFactory 를 구현하고 있지는 않는데 우선 getBean 메서드 부분부터 살펴보자.

* TODO BeanFactory 를 직접 정의하고 있는 인터페이스? 클래스? 를 찾아보자.

빈 획득을 빈 팩토리에게 위임하고 있다.

* TODO getBeanFactory 를 구현하고 있는 클래스를 찾아보자.

그리고 assertBeanFactoryActive 메서드의 자세한 스펙은 역시 API 문서를 참고하자.

조금만 이야기하자면 멀티스레드 환경에서 동시성을 보장하는

AtomicBoolean 을 사용해서 BeanFactory 가 활성화되어 있는지 체크하고 있다.

 

public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}
    
    	@Override
	public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException
}

 

TODO BeanFactory 를 직접 정의하고 있는 인터페이스? 클래스? 를 찾아보자

상속하고 있는 DefaultResourceLoader 은 이름부터 아닌 것 같은데 역시나 꽝.

 

public class DefaultResourceLoader implements ResourceLoader{...}
public interface ResourceLoader{...}

 

찾았다! 실무에서 인터페이스를 이렇게 까지 상속시켜준 적은 없는 것 같다.

스프링은 다양한 상황을 가정해서 조금씩 다른 기능을 추가하거나 수정해서 인터페이스들을 정의하고 있는 프레임워크인 것 같다.

그리고 도대체 얼마나 추상화 시켜 놓은 거야...

 

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable{...}
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver{...}
public interface HierarchicalBeanFactory extends BeanFactory{...}

 

TODO getBeanFactory 를 구현하고 있는 클래스를 찾아보자

두 개의 클래스가 구현하고 있는 것 같은데,

먼저 AbstractRefreshableApplicationContext 를 까 보자.

DefaultListableBeanFactory 타입의 빈 팩토리를 반환하고 있다.

이건 또 뭐지?? 점점 사고가 정지되어 가는 게 느껴진다... 

세세한 분석은 다음에 하는 걸로...

public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    @Nullable
    private volatile DefaultListableBeanFactory beanFactory
    
    @Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory == null) {
			throw new IllegalStateException("BeanFactory not initialized or already closed - " +
					"call 'refresh' before accessing beans via the ApplicationContext");
		}
		return beanFactory;
	}
}

 

다음으로 GenericApplicationContext 를 까 보자.

응? 여기에서도 DefaultListableBeanFactory 를 반환하고 있네.

* TODO DefaultListableBeanFactory 분석

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    private final DefaultListableBeanFactory beanFactory

    @Override
    public final ConfigurableListableBeanFactory getBeanFactory() {
	    return this.beanFactory;
    }
}

 

사고가 정지되기 시작해서 이번 분석은 여기까지 해서 정리하고,

다음에 또 살펴봐야겠다. 아직 뭐가 뭔지 잘 모르겠고 뒤죽박죽이고 엉망진창이긴 하지만

조금씩 정리하다 보면 답답한 마음이 뻥 뚫릴 날이 오지 않을까.

 

다음에 해 볼 것

* TODO DefaultListableBeanFactory 분석

* getBean 을 구현하고 있는 AbstractApplicationContext 이외의 클래스 분석

 

여기까지의 클래스 다이어그램

막상 그리고 보니 별거 없네.. 아 근데 왜 내 사고는 정지된 것인가..

클래스 다이어그램은 코드로 간단하게 다양한 UML 을 그릴 수 있는 PlantUML 을 사용하였는데

vscode, 인텔리제이 등에 플러그인이 만들어져 있다.

PlantUML 공홈

 

간단한 텍스트를 이용하여 멋진 UML 다이어그램을 만들 수 있는 오픈소스 도구입니다.

간단한 텍스트를 이용하여 쉽게 멋진 UML 다이어그램을 만들 수 있으며, 다양한 종류의 다이어그램을 제공하고 있습니다. 또한, 생성된 다이어그램을 PNG, LaTeX, EPS, SVG 와 같은 이미지로 변환할 수

plantuml.com

 

728x90
반응형

댓글