본문 바로가기

공부

스프링에서 빈 등록 과정 분석해보기

728x90

SringApplication

context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);

우리가 사용하는 SpringApplication이 실행되면 application context를 생성하고, 초기화 작업이 수행된다. 여기서 빈이 등록되는 부분은 this.refreshContext을 호출하는 라인이며 기본적으로 DefaultListableBeanFactory를 이용하게 된다.

DefaultListableBeanFactory

본격적으로 Bean을 등록하기 위해서 PostProcessorRegistrationDelegate에서 등록된 Post processor를 수행하며 ClassPathBeanDefinitionScanner에서 등록된 base package 하위 .class 파일을 순회하며 Bean definition을 수집한다.

AbstractAutowireCapableBeanFactory

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args)) {
        	...
        } else {
            return this.autowireConstructor(beanName, mbd, ctors, args);
        }
    }

ConstructorResolver

for(int paramIndex = 0; paramIndex < paramTypes.length; ++paramIndex) {
    Class<?> paramType = paramTypes[paramIndex];
    String paramName = paramNames != null ? paramNames[paramIndex] : "";
    ...

    Object sourceHolder;
    if (valueHolder != null) {
    	...
    } else {
        MethodParameter methodParam = MethodParameter.forExecutable(executable, paramIndex);
        if (!autowiring) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), "Ambiguous argument values for parameter of type [" + paramType.getName() + "] - did you specify the correct bean references as arguments?");
        }

        try {
            ConstructorDependencyDescriptor desc = new ConstructorDependencyDescriptor(methodParam, true);
            Set<String> autowiredBeanNames = new LinkedHashSet(2);
            sourceHolder = this.resolveAutowiredArgument(desc, paramType, beanName, autowiredBeanNames, (TypeConverter)converter, fallback);
            if (sourceHolder != null) {
                this.setShortcutIfPossible(desc, paramType, autowiredBeanNames);
            }

            allAutowiredBeanNames.addAll(autowiredBeanNames);
            args.rawArguments[paramIndex] = sourceHolder;
            args.arguments[paramIndex] = sourceHolder;
            args.preparedArguments[paramIndex] = desc;
            args.resolveNecessary = true;
        } catch (BeansException var25) {
        	...
        }
    }
}

실질적으로 Bean instance가 생성되는 곳으로, 생성자 주입 방식을 사용하는 Bean의 경우 주입받는 하위 Bean을 차례대로 생성하며, 최종적으로 대상 Bean이 생성된다.