카테고리 없음
                
              spring @bean
                머룽
                 2023. 4. 19. 09:55
              
              
            
            spring @Bean
스프링에 자주 사용되는 어노테이션으로 @Bean에 대해 살짝 맛만 볼라고 한다. 저번에 한번 얘기를 했는데ConfigurationClassParser클래스 doProcessConfigurationClass 메소드에 여러 메타 어노테이션을 파싱하는 부분이 있다.
...
// Process individual @Bean methods
Set<MethodMetadata> beanMethods = sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());
for (MethodMetadata methodMetadata : beanMethods) {
    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
...
@Bean
public ModelClass modelClass(){
    return new ModelClass();
}
BeanMethodInterceptor aop 프록시를 통해 해당 빈을 호출한다.
그리고 나서 DefaultSingletonBeanRegistry클래스에 싱글톤 빈이라고 저장해둔다.(아마도 여기에 모든 싱글톤이 있는 듯하다)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
singletonObjects 멤버 변수에서 꺼내서 주는 거다.
Object sharedInstance = getSingleton(beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
AbstractBeanFactory 클래스의 일부분이다.
if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            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);
}
else if (mbd.isPrototype()) {
    // Its a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        beforePrototypeCreation(beanName);
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
- singleton 일 경우
ModelClass hello = applicationContext.getBean("modelClass", ModelClass.class);
ModelClass hello2 = applicationContext.getBean("modelClass", ModelClass.class);
System.out.println(hello == hello2);
//true
- prototype 일 경우
ModelClass hello = applicationContext.getBean("modelClass", ModelClass.class);
ModelClass hello2 = applicationContext.getBean("modelClass", ModelClass.class);
System.out.println(hello == hello2);
//false