Spring.io - The Ioc Container

hyungjunn·2024년 7월 7일

Spring

목록 보기
1/1

The Ioc Container

Introduction to the Spring Ioc Container and Beans

  • ApplicaitonContext is a complete superset of the BeanFactory.
  • the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans.

Container Overview

  • In a Spring Boot scenario, the application context is implicitly bootstrapped for you based on common setup conventions.

Instantiation by Using an Instance a Factory Method

  • 개인적인 의견: 사용성이 있을까에 대한 의문점이 있음.
  • 링크

Bean Overview

Determining a Bean's Runtime Type

  • The recommended way to find out about the actual runtime type of a particular bean is a BeanFactory.getType call for the specified bean name. This takes all of the above cases into account and returns the type of object that a BeanFactory.getBean call is going to return for the same bean name.

Dependencies

Explains how you go from defining a number of bean definitions that stand alone to a fully recognized application where object collaborate to achieve a goal.

my summary
defining: a number of bean definitions that stand alone -> collaborate

Dependency Injection

Dependency Injection is a process in which a bean receives its dependencies from an external source instead of creating them itself.

Service Locator pattern과의 차이(참고: https://martinfowler.com/articles/injection.html#UsingAServiceLocator)

서비스 로케이터 패턴은 읽기 쉽고 명확하다는 특징이 있지만, 단점이 있다. 구현에 의존한다.

  • 요구사항이 바뀜에 따라 클라이언트 코드를 바꿔줘야 한다.
  • 테스트가 용이하지 못하다. 특히, 외부 api를 이용하는 경우 더욱 그렇다.

POJO

public class SimpleMovieLister {

	// the SimpleMovieLister has a dependency on a MovieFinder
	private final MovieFinder movieFinder;

	// a constructor so that the Spring container can inject a MovieFinder
	public SimpleMovieLister(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// business logic that actually uses the injected MovieFinder is omitted...
}

이렇게 아무 특별한게 없는 클래스를 POJO라고 한다. 인터페이스, 애노테이션, 특정 클래스에 대한 dependencies가 없다.

Because of DI, objects are decoupled from the responsibility of managing their dependencies. This makes your classses easier to test, as you can use stub or mock implementations of the dependencies.

Constructor Argument Resolution

Construct argument resolution matching occurs by using the argument's type.

Setter-based Dependency Injection

public class SimpleMovieLister {

	// the SimpleMovieLister has a dependency on the MovieFinder
	private MovieFinder movieFinder;

	// a setter method so that the Spring container can inject a MovieFinder
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// business logic that actually uses the injected MovieFinder is omitted...
}

이 class 역시 POJO다. 특정한 것에 종속성이 없기 때문이다.

Constructor-based or setter-based DI?

  • constructor -> programmatic validation of arguments
  • immutable objects
  • ensures not null
  • 그렇다면 setter injection은?
    - 어느 특정한 경우
    - 클래스 안에서 하나의 값을 지정해줄 때

The Spring team advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null.

Dependecy Resolution Process

The container performs bean dependency resolution as follows:

  • The Application context is created and initialized with configuration metadata that describes all the beans. Configuration metadata can be specified by XML, Java code, or annotations.
    -> Applicaiton context 는 생성(객체가)되고 빈들의 metadata 구성으로 초기화된다.
  • For each bean, its dependencies are expressed in the form of properties, constructor arguments, or arguments to the static factory method (if you use that instead of a normal constructor). These dependencies are provided to the bean, when the bean is actually craeted.
    -> 빈의 의존성은 다른 빈이 생성될 때, 그 다른 빈들에게 전달한다.
  • Each property or constructor argument is an actual definition of the value to set, or a reference to another bean in the container.
    -> 각 속성이나 생성자 인자는 설정할 값에 대한 실제 정의거나 컨테이너 안의 또다른 빈에 대한 참조다.
  • Each property or constructor argument that is a value is converted from its specified format to the actual type of that property or constructor argument. By default, Spring can convert a value supplied in string format to all built-in types, such as int, long, String, boolean and so forth.
    -> 각 속성 또는 생성자 인자는 값이다 그것의 특정 포맷에서 실제 타입으로 전환되는. 고정적으로 스프링은 문자열 타입을 int, long, String, boolean 등등으로 바꿔준다.

The Spring container validates the configuration of each bean as the container is created. However, the bean properties themselves are not set until the bean is actually created. Beans that are singleton-scoped and set to be pre-instantiated (the default) are created when the container is created. Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested. Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mismatches among those dependencies may show up late — that is, on first creation of the affected bean.
-> 스프링 컨테이너가 생성될 때, 빈 설정을 확인한다. 그러나 빈의 속성들은 실제로 생성될 때까지 설정되지 않는다. 싱글톤 스코프의 빈만 컨테이너가 생성될 때 생성된다.

Circular dependencies

public class ACircularObject {  
  
    private final BCircularObject bCircularObject;  
  
    public ACircularObject(BCircularObject bCircularObject) {  
        this.bCircularObject = bCircularObject;  
    }  
}
public class BCircularObject {  
  
    private final ACircularObject aCircularObject;  
  
    public BCircularObject(ACircularObject aCircularObject) {  
        this.aCircularObject = aCircularObject;  
    }  
}
@Configuration  
public class CircularDependencyConfig {  
  
    @Bean  
    public ACircularObject aCircularObject(BCircularObject bCircularObject) {  
        return new ACircularObject(bCircularObject);  
    }  
  
    @Bean  
    public BCircularObject bCircularObject(ACircularObject aCircularObject) {  
        return new BCircularObject(aCircularObject);  
    }  
  
}
public class CircularMain {  
    public static void main(String[] args) {  
        ApplicationContext context = new AnnotationConfigApplicationContext(CircularDependencyConfig.class);  
  
        ACircularObject aCircularObject = context.getBean(ACircularObject.class);  
        BCircularObject bCircularObject = context.getBean(BCircularObject.class);  
  
        System.out.println("aCircularObject = " + aCircularObject);  
        System.out.println("bCircularObject = " + bCircularObject);  
        // Requested bean is currently in creation: Is there an unresolvable circular reference?  
        // 이라고 에러가 발생한다.  
    }  
}

정말 필수적인 빈만 컨테이너 생성시에 생성하고 나머지는 요청에 따라 생성할 수 있도록 하여, 초반 빌드 시간을 단축시키고 에러가 어느곳에서 나는지 알기 쉽게해준다.

Autowiring Collaborators

The Spring container can autowire relationships between beans by inspecting the information in the ApplicaitonContext

0개의 댓글