Inversion Of Control

This phenomenon is Inversion of Control (also known as the Hollywood Principle - "Don't call us, we'll call you").

A framework embodies some abstract design, with more behavior built in. Inversion of Control is a key part of what makes a framework different to a library.

The main control of the program was inverted, moved away from you to the framework.

The Dependency Injection pattern is a more specific version of IoC pattern, and is all about removing dependencies from your code.

ReadMore - Martinfowler - Inversion of Control Containers and the Dependency Injection pattern

Analyzing Spring IOC Source Code

Analyzing Spring IOC Source Code:

Spring IoC Container 에서 Bean 가져오기, 삭제 등의 기본 작업이 정의되어있는 핵심 인터페이스는 BeanFactory Interface 이다. The root interface for accessing a Spring bean container.

public interface BeanFactory {
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

BeanFactory 의 기본 구현체는 DefaultListableBeanFactory 이다. Typical usage is registering all bean definitions first (possibly read from a bean definition file), before accessing beans. 빈을 등록할 때는 Reflection 을 사용하는데, BeanDefinition (빈 설정 메타 정보) 를 활용하여 빈을 생성한다.

public interface BeanDefinition {
    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    String getBeanClassName();
    void setBeanClassName(String beanClassName);
    String getScope();
    void setScope(String scope);
    boolean isSingleton();
    boolean isPrototype();
    String getFactoryMethodName();
    void setFactoryMethodName(String factoryMethodName);
    String getFactoryBeanName();
    void setFactoryBeanName(String factoryBeanName);
    String[] getDependsOn();
    void setDependsOn(String... dependsOn);
    boolean isLazyInit();
    void setLazyInit(boolean lazyInit);
    ConstructorArgumentValues getConstructorArgumentValues();
    MutablePropertyValues getPropertyValues();
    boolean isAutowireCandidate();
    void setAutowireCandidate(boolean autowireCandidate);
}

핵심은 두 메서드이다. getBeanClassName() 메서드는 빈의 클래스 이름을 반환하고 getPropertyValues() 메서드는 빈의 속성 값을 반환한다. 구체적인 구현은 DefaultListableBeanFactory 를 확인하면 된다.

Bean creation:

  • In DefaultListableBeanFactory, the creation of bean is done through createBean() method.

Bean’s dependency injection process:

  • In DefaultListableBeanFactory, the dependency injection of the bean is done through the applyPropertyValues() method
  • During the property assignment process, if the property value is a reference type, it will try to do autowiring.
  • In the resolveValueIfNecessary() method, if the value of the property is a BeanDefinitionHolder object or a RuntimeBeanReference object, it means that the property is a reference type and needs to be autowired. At this point, the resolveReference() method is called for reference resolution and autowiring.