SSAFY11th-book-study / book-study

SSAFY 11기 6반의 '토비의 스프링 스터디'
0 stars 0 forks source link

[1.7.3] 의존관계 검색과 ApplicationContext #14

Closed gmelon closed 7 months ago

gmelon commented 7 months ago

p.120에 보면 아래와 같이 AnnotationConfigApplicationContext를 통해 ConnectionMaker를 검색해 사용하고 있습니다.

image

코드에서는 AnnotationConfigApplicationContextnew 키워드를 통해 새롭게 생성해서 사용하고 있습니다. 또한, 책에서 말한 것처럼 DL을 사용하면 의존관계를 필요로 하는 클래스가 꼭 스프링의 빈으로 관리되지 않아도 됩니다. 여기서 두 가지 의문이 들었습니다.

  1. 위 코드와 같이 의존관계를 검색하면 스프링이 뜰 때 생성되는 context에서 주입 받은 빈과는 다른 인스턴스가 주입되는가?
  2. 그렇다면 AnnotationConfigApplicationContextnew 할 때마다 'DI 컨테이너' 가 새롭게 생성된다고 할 수 있는건가?

어떻게 생각하셨는지 궁금합니다.

gmelon commented 7 months ago

아래와 같이 Bean 으로 등록된 SomeObject 가 있고

SomeObject

@Component
public class SomeObject {

    public SomeObject() {
        System.out.println(this);
    }

}

이를 등록하는 Config 클래스가 있고,

SomeDao

@Configuration(proxyBeanMethods = false)
public class SomeDao {
    @Bean
    SomeObject someObject() {
        return new SomeObject();
    }
}

빈으로 등록되지 않은 아래와 같은 서비스에서 SomeObject를 DL 하고 있다.

PlainService

public class PlainService {

    private SomeObject someObject;

    public PlainService() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SomeDao.class);
        this.someObject = context.getBean("someObject", SomeObject.class);

        System.out.println(this.someObject);
    }
}

CommandRunner를 사용해 PlainService가 생성되도록 했다. image

이를 실행해보면 아래와 같이 스프링이 뜰 때 자동으로 주입되는 빈과 직접 찾은 빈이 서로 다른 오브젝트를 가리키고 있음을 알 수 있다. image

따라서, 스프링이 뜰 때 생성되는 ApplicationContext와 new 를 통해 생성되는 ApplicationContext는 서로 별개의 것임을 알 수 있다.

이에 따라, 동일한 클래스에서 생성한 서로 다른 Context에서는 서로 다른 object를 반환하고 같은 Context에서는 getBean을 여러번 호출해도 동일한 object 를 반환한다.

public class PlainService {

    private SomeObject someObject;

    public PlainService() {
        AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext(SomeDao.class);
        System.out.println(context1.getBean("someObject", SomeObject.class)); // com.example.demo.SomeObject@56928e17
        System.out.println(context1.getBean("someObject", SomeObject.class)); // com.example.demo.SomeObject@56928e17

        AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext(SomeDao.class);
        System.out.println(context2.getBean("someObject", SomeObject.class)); // com.example.demo.SomeObject@338766de
        System.out.println(context2.getBean("someObject", SomeObject.class)); // com.example.demo.SomeObject@338766de
    }
}