자프링 공화국의 성경. 스프링 프레임워크의 빈 생명주기를 조금 더 볼까한다.

요즘 다 스프링 부트 쓰고있으니까 SpringApplication.run() 이거 기준으로 설명하는게 제일 익숙할 거라 생각한다.


스프링 빈 생명주기를 좀더 상세히 보면

부서버 구동시 run() 메서드가 실행되며 그 메서드의 스텝을 따라 들어가면


SpringApplication.run()
-> createApplicationContext()
-> load(context, sources) // BeanDefinition 스캔, 파싱
-> refreshContext(context)

-> applicationContext.refresh() // 빈 생성 진입점


이후 사이클은 코드에 보이는 것과 같이


prepareRefresh -> prepareBeanFactory -> BFPP -> BPP -> 이벤트처리, 메세지소스, 리스너 등록 뭐 기타등등 으로 진행됨을 확인할 수 있다.




그럼 여기서 실제 빈을 생성해서 가져오는 곳은
finishBeanFactoryInitialization 메서드 실행부분인데
이건 도식화해서 보면


refresh()

-> finishBeanFactoryInitialization()
-> preInstantiateSingletons()
-> getBean(beanName)
-> doGetBean()
-> getSingleton(beanName, () -> createBean(...))


이런식으로 표현할 수 있다.


결국 여기서 모든 BeanDefinition 이름을 순회하면서, 조건(싱글톤 + non-lazy + non-abstract 등)을 만족하면 getBean(beanName)을 호출한다.


그럼 또 들어가서 봐야지 싱글톤은 다음에 설명하도록하고 (어떻게 프라이빗으로 생성자 폐쇄 같은거 안 해도, 싱글톤으로 컨테이너 반환하는지나 뭐 그런거 있음)


겟빈 쳐서 나오는 두겟빈 보자.


좀 길다.


중간에 박스쪽만 봐라 일단

mbd(빈 설정 등록된거)가 싱글턴 스코프면 람다 만들어서 createBean()를 getSingleton으로 넘긴다. (저 메서드가 싱글턴으로 구현한 구현체)

프로토타입 스코프는 그딴거없이 바로 만들어서 싱글턴반환아님 스코프 설ㅈ어하면 다른 객체로 튀어나옴(동일성 보장 x)


AbstractAutowireCapableBeanFactory 이 추상클래스는 AbstractBeanFactory를 상속한 클래스인데 여기서 실제로 구현된 createBean을 볼 수 있다.




응 ㅅㅂ 저기 또 들어가야 함 아직도 멀었음 ㅂㅅ같은거




대충 저 블럭은 Instantiate라고 하는데 인스턴스 만들기 내부에서 인스턴스 어떻게 생성할지 먼저 정한다.

아마 스프링 배울떄 DI나 주입 관련 배우면서 candidate constructors for autowiring 이런 키워드로 찾아보면 내용 나온다

다시 돌아와서 어떻게 인스턴스 만들지 결정한다음 만들고 해당 인스턴스를 래핑해서 이제서야 bean 이라는 이름의 Object로 할당한다.

근데 이것도 아직 DI건 초기화던, AOP 이딴거 하나도 안탄 raw Bean 상태임.


다음 빨간 박스 가기 전 싱크로나이즈 블럭은 대충 RootBeanDefinition 확정하는건데 메타데이터 캐싱해서 리플렉션 줄이려고 하는 곳임 대충 나도 그거밖에 모름 걍 1회용 캐시임


내려와서 박스 보면 여기는 순환참조 대응해서 싱글톤 초기 노출하는 부분임

주석 번역기 돌리면 됨

= BeanFactoryAware 같은 라이프사이클 인터페이스가 트리거해서 순환참조가 발생하는 경우도 있기 때문에, 싱글톤을 미리 캐싱해 둔다.


조건은 3개 전부 참일 경우인데

1. 싱글톤 스코프

2. 순환참조 허용 플래그

3. 해당 빈이 생성중인지 여부


그렇게되면 이제 진짜 스프링 빈 캐시등록 뭐 3단 캐시 하는 부분이 박스 내부 하단 addSingletonFactory() -> 람다고


그다음 파퓰레이션에서 DI 주입 -> 다음 초기화(initialize) 하면 니가 쓸 준비 된거다.

(니가 등록한 빈이 한참 런타임 돌다가 사라질때가 되면 destroy 트리거 잡아서 부숨)


무튼 이게 간단히본 스프링 빈 라이프사이클 앞 부분임 인텔리제이 최신버전 쯤 오면 이제 디컴파이 ㄹ아니고 소스 자체를 다운 받아줘서 보기 더 편해졌다 많이들 츄라이해 봐라.

재밌다.

화이팅이다 모두.



=====================================================


p.s. 마지막 빨간박스는 아까 얼리싱글턴 익스포저한거 랑 최종 객체랑 정합성 맞추는 부분이라 걍 뒤로 미룸

조건 분기 잘 해석해서 봐라 이해 될거다

1차 2차 3차 캐시 뭔지 알면 더 빠를건데 그냥 대충 처음에 만든거(1차확정)혹은 이미 얼리에 만들어진거(2차)에 있으면 그 만들어진걸로 정합 맞춘다가 조건의 핵심임


예외 메세지 해석

= 순환참조 과정에서 raw로 주입됐는데, 최종적으로 wrapping(프록시)이 되었다. 그래서 다른 빈들이 최종 버전을 쓰지 않는다. 이는 과도하게 eager type matching한 결과일 수 있다.


순환참조 때문에 어떤 빈들이 이 빈을 raw 버전으로 주입받았는데

최종적으로는 이 빈이 프록시로 감싸져 버리면

의존하는 빈들은 raw를 들고 있고, 컨테이너가 최종으로 노출하는 건 프록시가 되니까 일관성 꺠진다 터질게~ 이거임 그냥 몰라도 됨


그리고 이 분기까지 마치면 반환되는 익스포저는 프록시가 있으면 프록시, 없으면 얼리참조로 정렬한 객체

둘 뿐임 (raw bean 아님)


틀릴수도 있음. 필요 내용은 알아서 찾아봐라.