본문 바로가기

Spring/Spring

(SPRING) getBean()에 대해서

bean의 인스턴스는 언제 어디서 생성되는 것일까?

Where?

bean의 인스턴스는 BeanUtils 클래스에서 생성된다.

좀 더 자세히 말하자면 instantiateClass 메서드에서 Reflection의 newInstance를 함으로써 인스턴스가 생성된다. 

 

When?

getBean을 호출함으로써 인스턴스가 생성되고 스프링 컨테이너의 Singleton으로 등록이 된다.


자세한 내용을 코드를 통해서 살펴보도록하자 코드만큼 확실한 것은 없으니깐?ㅎㅎ

 

public class MyApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context
                                = new AnnotationConfigApplicationContext(Config.class);

        MyBean myBean = context.getBean("myBean", MyBean.class);
        myBean.doSomething();

    }
}

getBean을 하는 과정은 디버깅을통해서 알아보자

 


finishBeanFactoryInitialization(beanFactory);

이전에 포스팅하였던 refresh()에서 등록이 된다.

처음에는 잘 이해가 가지 않았다. 어떠한 부분이 이해가 가지 않았냐면 

AnnotationConfigApplicationContext의 객체가 생성이 되고 해당 콘텍스트를 getBean을 하면 기존에 만들어놓았던 singleton에 해당하는 객체를 호출하는 것이었다. 내가 알기로는 getBean을 하면 그때서야 인스턴스가 생성되고 singleton이 만들어진다고 알고 있었는데 말이다.

답은 AnnotationConfigApplicationContext 객체 생성 시 refresh()의 finishBeanFactoryInitialization(beanFactory); 에서 이미 getBean을 해서 인스턴스를 생성하고 singleton을 이미 생성을 해두었던 것이다.🤪

 

이제 본격적으로 getBean을 파헤쳐보자😆

 

 

preInstantiateSingletons

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.

		beanFactory.preInstantiateSingletons();
	}

위와 같이 현재 beandefinitionNames에는 7개의 정보가 들어있다. 해당 정보를 String을 제네릭으로 하는 리스트에 담아서 루프를 돌린 다음 인스턴스를 생성 후 싱글톤으로 등록한다.


getBean의 등장

아래와 같이 드디어 그렇게 찾던 getBean을 찾았다.

getBean은

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) 여기로 간다.

 

우리는 config와 myBean만 보도록 한다.

Object sharedInstance = getSingleton(beanName);

이미 등록된 싱글톤이 있는지를 체크하는데 없기 때문에 null을 반환한다.

 

Create bean Instance

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
        // Explicitly remove instance from singleton cache: It might have been put there
        // eagerly by the creation process, to allow for circular reference resolution.
        // Also remove any beans that received a temporary reference to the bean.
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

ing...