[Spring 공부일지] Spring 컨테이너와 Bean

최원석·2024년 8월 3일

Spring 공부

목록 보기
4/5

Spring 컨테이너

ApplicationContext를 Spring 컨테이너라고 한다.

Spring 컨테이너는 Spring에서 자바 객체들을 관리하는 공간을 말한다.

자바 객체를 Spring에서는 Bean이라고 하기 때문에, Spring 컨테이너에서 Bean의 생성부터 소멸까지를 관리하는 곳이라고 할 수 있다.

Spring 컨테이너는 @Configuration 이 붙은 AppConfig를 설정 정보로 사용한다. @Bean 어노테이션이 붙은 메서드를 모두 호출하여 반환된 객체를 모두 Spring 컨테이너에 등록한다.

스프링 컨테이너에 등록된 객체 → “스프링 빈”

컨테이너 구성

컨테이너는 BeanFactory 와 ApplicationContext 으로 나눌 수 있다.

ApplicationContext컨테이너가 BeanFactory의 기능을 포괄하기에 때문에 대부분의 경우에는 ApplicationContext 을 사용한다.

Bean

Bean 알아보기

Bean은 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트.

즉! 스프링 컨테이너가 관라하는 자바 객체를 뜻하며, 하나 이상의 Bean을 관리한다.

Bean 등록하기

Spring에 Bean을 등록하는 방법으로는 아래 2가지가 있다. ( XML을 이용한 방법도 있지만 생략)

  • @Bean 어노테이션 이용
  • @Component, @Controller, @Service, @Repository

@Bean 어노테이션 이용

@Bean 어노테이션의 경우 메서드를 Bean으로 등록하기 위한 어노테이션

메서드에 붙여 메서드를 통해 반환되는 객체를 Bean으로 등록한다.

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

@Component, @Controller, @Service, @Repository

ex) @Service를 이용한 Bean 등록

@Service
public class MemberService {
    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }

    public Long join(Member member){
        validateDuplicateMember(member);
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
            .ifPresent(m -> {
                throw new IllegalStateException("이미 존재하는 회원입니다.");
            });
    }

    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }
}

@Component

@Component 어노테이션의 경우 개발자가 직접 작성한 Class를 Bean으로 등록하기 위한 어노테이션

@Component
public class HelloComponet{    
	public HelloComponet() {        
		System.out.println("Hello Componet!!");    
		}
}

개발자가 작성한 Class를 Bean에 등록하기위해 Class 상단에 @Component를 붙였다.

@Autowired

@Component를 통해 등록된 Bean은 다른 Class에서 @Autowired를 사용해 의존성을 주입할 수 있다.

@Component
public class Brain {
    . . .
}

@Component
public class Person {

    private Brain brain; 
    . . .
    
    }
}
❓ 의존성 ( D.I ) Person Class는 항상 Brain Class를 사용해야한다. 그러므로 Person은 Brain에 의존한다고 볼 수 있다.
public class Person {

    private Brain brain;

    @Autowired
    public void setField(Brain brain) {
        this.brain = brain
    }
}

DI에는 필드 주입, 생성자 주입, setter 주입으로 3가지가 있지만, 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장

❗ @AutoWired 를 통한 DI는 스프링이 관리하 는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

@Controller, @Service, @Repository을 이용해 Bean 등록이 가능한 이유는 ?

@Controller, @Service, @Repository 어노테이션들은 @Component를 포함하기 때문에 가능하다.

ex) @Service의 구성

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.stereotype;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component  <---- 포함하고 있음
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

0개의 댓글