인프런 커뮤니티 질문&답변

lbd4946@gmail.com님의 프로필 이미지

작성한 질문수

스프링 핵심 원리 - 기본편

옵션 처리

TestBean 클래스의 자동 빈등록 이유

해결된 질문

작성

·

453

8

public class AutowiredTest {

@Test
public void autowiredOption() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
}

위의 예제를 보면 TestBean이 자동으로 컨테이너에 빈으로 등록된다고 하셨는데
@Autowired가 있기 때문에 그런 것 같은데 맞나요?

답변 11

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. lbd4946님^^

추가 질문을 듣고 어떤 것을 물어보신지 이해가 되었습니다. 제가 조금 더 풀어서 설명을 해드릴께요.

1. 먼저 new AnnotationConfigApplicationContext(TestBean.class); 라고 하면 TestBean이 스프링 빈으로 등록됩니다. 이때 TestBean 자체는 아무 애노테이션이 없어도 등록이 됩니다^^! 처음에는 설정 정보가 필요하니, 보통 TestBean 같은 설정 정보를 등록하는 용도로 많이 사용합니다.

2. @Bean은 TestBean 같은 곳에 아마도 추가되어 있을거에요. 이렇게 TestBean 같은 스프링 빈에 @Bean이 붙어있으면 이 메서드들을 호출해서 스프링 빈으로 등록합니다.

3. @Configuration, @Component는 @ComponentScan이라는 자동 등록 기능에 의해서 스프링 빈에 등록될 수 있습니다. TestBean에도 아마 @Configuration이 붙어있을 건데, 이때는 new AnnotationConfigApplicationContext(TestBean.class)라고 이미 적어주었기 때문에 자동 등록 기능에 의해서 스프링빈에 등록된 것은 아니고, 스프링 컨테이너 생성 시점에 바로 스프링 빈으로 등록됩니다. 물론 @Configuration 자동 등록 기능에 의해서도 스프링 빈으로 등록될 수 도 있습니다^^

감사합니다.

1

이해가 되었습니다!!! 

감사합니다. 혼자 정리 다시 해보면서 확실히 이해하면 될 것 같아요!!

감사합니다!!

1

김영한님의 프로필 이미지
김영한
지식공유자

질문을 자세히 잘 풀어서 남겨주셔서 감사합니다^^

1. TestBean에 @Configuration이 없고, @Bean도 없으면: 스프링 빈으로만 등록됩니다.

2. TestBean에 @Configuration이 달렸고, @Bean도 존재: 스프링 빈으로 등록되고, 추가로 스프링이 @Bean을 보고 설정 정보로 사용합니다. 여기서 @Component는 없어도 됩니다. (@Component는 @ComponentScan의 대상으로만 사용됩니다.)

추가로 @Bean은 아무 스프링 빈에 등록되어 있어도 스프링이 인지해서 스프링 컨테이너에 해당 빈을 등록합니다. 예를 들어서 다음과 같은 MemberService가 스프링 빈으로 등록되어 있다고 할 때, 여기에 @Bean이 있어도 됩니다. 스프링이 MemberService를 스프링 빈으로 등록하기만 하면, 그 안에 @Bean 이라고 붙은 정보를 다 찾아서 스프링 컨테이너에 등록해줍니다^^!

class MemberService{ 

    @Bean

    public Hello() {

      return new Hello();

    }

}

도움이 되셨길 바래요^^ 혹시 의문이 해결되지 않았으면 추가로 질문남겨주세요 :)

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. TestBean님^^

@Autowired때문은 아니구요.

new AnnotationConfigApplicationContext(xxx)에 인자로 넘어온 클래스는 자동으로 스프링 빈으로 등록됩니다.

즐거운 추석 되세요^^!

0

감사합니다

0

김영한님의 프로필 이미지
김영한
지식공유자

ㅎㅎ 괜찮아요^^! lbd4946님 스프링 핵심 원리 강의이니 확실하게 이해하는게 중요합니다!

앞에서 이야기하신 부분들을 잘 이해하셨습니다.

그런데 추가로 설명하신 부분은 좀 모호한 부분이 있어서 혹시나 해서 제가 추가 설명을 드릴께요. 다음 부분이요.

------------

추가로 ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
ac.getBean(...); 을 하는 행위를 해주는 것이 @Autowired 입니다.

------------

이 코드 자체는 @Autowired와는 관계가 없습니다.

ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);

코드를 풀어서 말씀드리면

1. new AnnotationConfigApplicationContext(AutoAppConfig.class);를 실행하면 스프링 컨테이너가 생성되고, 스프링 빈들도 모두 생성이 되고, 초기화 작업까지 끝이 납니다.

2. 이 과정에서 스프링 빈에 @Autowired라는 애노테이션이 있으면 의존관계 자동 주입이 일어납니다.

(@Autowired라고 하면 결국 스프링 빈 내부에서는 ac.getBean(...)이 일어난다고 생각하시면 됩니다.(디테일한 차이는 있습니다.))

3. ApplicationContext ac = 이렇게 생성이 끝난 스프링 컨테이너의 참조값을 ac에 넣어둡니다.

감사합니다. 혹시라도 잘 해결되지 않은 부분이 있으면 언제든지 편하게 질문주세요^^!

0

답변 감사합니당

자꾸 도돌이표 질문을 드리는 것 같아 죄송합니다 ㅜ.ㅜ

이해한게 맞는지 확인 부탁드립니다!!!

AnnotationConfigApplicationContext빈의 용도는 이름 그대로 어노테이션으로 설정된 클래스를 읽어 컨테이너를 생성하고

컨테이너에 빈으로 등록하는 역할을 하는 것이고, TestBean에 @Configuration이 달려있지 않아도 동일하게 빈으로 등록을 해줍니다.

다만 @Bean이 클래스 내에 정의 되어 있다면 같이 빈으로 등록을 해주는 것이구요.

결국 생명주기?? 라고 해야할지 모르겠지만, 생명주기락고 한다면 크게 3가지로 **컨테이너 생성** -> **빈등록** -> **의존관계주입**

으로 생각합니다. 

AnnotationConfigApplicationContext는 BeanFactory의 하위 레벨이기 때문에 결국 컨테이너이고, 

그렇기 때문에 new AnnotationConfigApplicationContext(TestBean.class)를 했을 때 TestBean에 @Configuration이 없지만, 

컨테이너를 먼저 생성 후 TestBean을 등록을 할 수 있습니다.

@Component는 3가지 생명 주기를 손쉽게 할 수 있게 해주는 것이구요. 

다만, @Configuration이 없을 때의 단점은, 싱글톤이 보장되지 않는다는 것 이구요. 자바 왜냐하면, 결국 자바코드이기 때문에

아래와 같을 때 memberService()에 있는 return new MemberMemoryRepository(); 1번, 

memberRepository()에 있는 return new MemberMemoryRepository(); 1번 
총 2번이 생성 되기 때문에 memberService()의 값과, memberRopository()의 값은 싱글톤이 아니게 된니다.

public class AppConfig {

    @Bean
    public MemberService memberService() {
        System.out.println("AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        System.out.println("AppConfig.memberRepository");
     }
}

추가로 ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
ac.getBean(...); 을 하는 행위를 해주는 것이 @Autowired 입니다.

감사합니다!!!  친철한 답변 감사합니다!!

0

김영한님의 프로필 이미지
김영한
지식공유자

답변을 조금 더 보충드릴께요.

new AnnotationConfigApplicationContext(TestBean.class); 가 있을 때

1. TestBean에 @Configuration이 없고, @Bean도 없으면: TestBean만 스프링 빈으로만 등록됩니다.

2. TestBean에 @Configuration이 달렸고, @Bean도 존재: TestBean이 스프링 빈으로 등록되고, 추가로 스프링이 @Bean을 보고 설정 정보로도 사용합니다.

사실 스프링 컨테이너는 스프링 빈 중에서 @Bean이 등록된 메서드가 있으면 모두 스프링 빈으로 등록합니다^^!

그렇게 하려면 스프링 빈이 최소 하나는 등록이 되어 있어야 하는데,

그게 바로 new AnnotationConfigApplicationContext(TestBean.class); 라고 이해하시면 됩니다.

혹시 의문이 해결되지 않으면 편하게 답변 남겨주세요^^

안녕하세요. 답글 달아주시는것을 보고 이해 안되는게 있어 질문드립니다.

-----------------------------

답변

new AnnotationConfigApplicationContext(TestBean.class); 가 있을 때

1. TestBean에 @Configuration이 없고, @Bean도 없으면: TestBean만 스프링 빈으로만 등록됩니다.

2. TestBean에 @Configuration이 달렸고, @Bean도 존재: TestBean이 스프링 빈으로 등록되고, 추가로 스프링이 @Bean을 보고 설정 정보로도 사용합니다.

---------------------------------

2번 답변을 보시면 @Bean을 통해 추가로 스프링이 @Bean을 보고 설정 정보로도 사용합니다 라고 말씀하셨는데 여기서 말씀하신 설정정보가 어떤건지 알수있을까요? 

@Bean 이 없는 1번의 경우에는 TestBean이 스프링빈으로만 등록되고 설정정보로 사용 안된다는건 Test빈이 가지고 있는 정보는 사용하지 않는다는 뜻인가요?

오래전 답변이시지만, 이해가 잘 가지않아 질문드립니다. 감사합니다!

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 심모님 너무 오래된 질문이어서 궁금하신 내용을 코드로 직접 테스트 보시고 정리해서 새로 올려주시면 도움을 드리겠습니다.

감사합니다.

0

결국

new AnnotationConfigApplicationContext(TestBean.class);

위의 코드가

**@Configuration**과 **@Bean**으로 등록 되어 있으면 등록된 빈 설정 정보를 가져오게 되는 것 이고,

없다면 위의 코드에서 빈으로 등록하게 되는 것이 맞는 건가요?

0

답변 감사합니다!!! 추가 질문이 있습니다.

먼저 예제는 아래와 같은 예제입니다.

1. TestBean에는 @Configuration이 없고, @Bean도 없습니다. 해당 예제는 주입할 스프링 빈이 없을 때 통과 시키기 위한

예제입니다. 하지만 이런 상황에 TestBean을 스프링 빈으로 등록하기 위해 

new AnnotationConfigApplicationContext(TestBean.class);

위의 코드로 빈 등록을 한 것이라고 이해 되었습니다. 즉, TestBean 클래스에서 아무런 정보도 없지만 해당 코드로 인해

해당 클래스를 빈으로 등록할 수 있는 것 같습니다.

2. 만약 TestBean에 @Configuration이 달렸고, @Bean도 존재 하거나 @Component이 달렸을 때는

컨테이너가 생성될 때!!! 빈으로 등록하고,

new AnnotationConfigApplicationContext(TestBean.class);

여기서는 등록된 정보를 가져오는 역할만 하는 것으로  보이는데 맞을까요?

즉, 1번일 때의 역할은 등록도 하고 설정정보를 가져오기도 하며,

2번 일 때는 설정정보만 가져오는 것으로 이해 되었습니다.

앗!! 혹시 오해 하시고, 더욱 자세한 답변을 주실까봐 남겨요

@Bean이 존재하는 클래스에 @Configuration이 있을 때와 없을 때의 차이는

강사님께서 답변 해주셔서 알고 있습니다

없어도 스프링 빈으로 등록은 되지만,

존재할 때는 싱글톤이 보장되지만, 없을 때는 보장되지 않는다!!

public class AutowiredTest {

    @Test
    public void autowiredOption() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
        TestBean bean = ac.getBean(TestBean.class);
        System.out.println("bean = " + bean);
    }

    static class TestBean {

        //호출 안됨
        @Autowired(required = false)
        public void setNoBean1(Member member) {
            System.out.println("setNoBean1 = " + member);
        }
        //null 호출
        @Autowired
        public void setNoBean2(@Nullable Member member) {
            System.out.println("setNoBean2 = " + member);
        }
        //Optional.empty 호출
        @Autowired(required = false)
        public void setNoBean3(Optional<Member> member) {
            System.out.println("setNoBean3 = " + member);
        }
    }
}

0

제가 이해를 잘못하고 있었나 봐요

AnnotationConfigApplicationContext(xxx.class)
의 기능은 이미 @Bean, @Comfiguration, @Component에 의해 등록된 bean을 가져오는 것으로 이해 했는데 아닌가요?