BACKEND/JAVA & SPRING

@Configuration이란 (w/ IoC, DI)

이-프 2023. 11. 9. 16:47

Spring을 공부할 때, Spring은 객체를 Bean으로 등록해서 이를 사용함을 알 수 있는데, 여기서 @Configuration 정보가 나오게 된다. Spring의 흐름을 제대로 파악하고자 이번엔 @Configuration을 포스팅한다. 🌱

@Configuration이란?

Spring에서는 Bean을 수동으로 등록할 때, 설정 class 위에 @Configuration을 추가하고, @Bean을 사용해서 수동으로 Bean을 등록할 수 있다.

@Configuration
public class PasswordEncoderConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
		//이제 passwordEncoder를 사용하기 위해서는 @Autowired를 작성해줘야한다.(DI)
}

객체 생성 방법들

예를 들어, MemberService란 객체를 사용해야한다고 가정하자. 객체를 사용한다는 의미는 객체의 메소드와 필드를 사용한다는 뜻이고, 이를 위해선 객체를 “생성”부터 해야한다.

이때, “의존한다” = “사용한다”

  1. 객체 생성을 MemberService 그 자체에서 할 경우
    MemberService memberService = new MemberService();
  1. 객체 생성을 AppConfig에 위임했을 경우
    AppConfig appConfig = new AppConfig();
    MemberService memberService = appConfig.memberService();

  1. Spring Container을 사용해서 위임했을 경우
    ApplicationContext applicationContext = 
    								new AnnotationConfigApplicationContext(AppConfig.class)
                      //└ Annotation으로 만든 AppConfig 파일로 ApplicationContext를 만들겠다.
    
    MemberService memberService = 
    			//applicationContext.getBean("빈 이름", 빈 형태)
    			applicationContext.getBean("memberService", MemberService.class);
    //아직까지도 Spring 컨테이너에 맡기기만 했지, 제어권 100%를 준 느낌은 x 
    • new AnnotationConfigApplicationContext(AppConfig.class) : @Configuration이 붙은 AppConfig 파일로 ApplicationContext를 만들겠다.
    • applicationContext.getBean("memberService", MemberService.class) : applicationContext.getBean("빈 이름", 빈 형태)
    • 3번 방법은 Spring Container에 Bean을 등록하긴 했으나, 제어권을 확실히 줬다고 말할 수 없다.
    @Configuration
    public class AppConfig {
    	@Bean //스프링 빈 등록하기
    	public MemberService memberService(){
    			return new MemeberService();
    	}
    	@Bean
    	pulbic Test test(){
    			return new Test(memberService()); // 싱글톤 패턴에 의해 2개 생성이 아닌 1개만 생성된다.
    	}
    } 
  1. DI의 등장 ⇒ Spring에게 제어권을 완전히 넘겨준 case
    @Autowired 
    MemberService memberService;
    • @Autowired : Spring Container에 등록한 Bean에게 의존관계의 주입이 필요할 때 작성하는 Annotation
    AppConfig.java
    @Configuration
    public class AppConfig {
    	@Bean //스프링 빈 등록하기 set
    	public MemberService memberService(){
    			return new MemeberService();
    	}
    	@Bean
    	pulbic Test test(){
    			return new Test(memberService()); // 싱글톤 패턴에 의해 2개 생성이 아닌 1개만 생성된다.
    } 

@Configuration의 역할

  1. Bean을 등록할 때 Singleton이 되도록 보장해준다.
  1. Spring Container가 Bean을 관리할 수 있도록 한다.

    example )

    public class MyBean {
    		public MyBean() {
    			System.out.println("MyBean instance created");
    		}
    }
    public class MyBeanConsumer {
    		public MyBeanConsumer(MyBean myBean) {
    				System.out.println("MyBeanConsumer created");
    		}
    }
    @Configuration
    public calss AppConfig {
    		@Bean
    		public  MyBean myBean() {
    				return new MyBean(); //호출 1회
    		}
    
    		@Bean
    		public MyBeanConsumer myBeanConsumer() {
    				return new MyBeanConsumer(myBean()); //호출 2회
    		} 
    }

  • @Configuration을 작성시,
    MyBean instance created
    MyBeanConsumer created
  • @Configuration을 제거시, 호출 2번됨
    MyBean instance created
    MyBean instance created
    MyBeanConsumer created

∵ @Bean만 사용시 Spring Bean으로 등록은 가능하나, Singleton이 유지되지 않는다.

IoC와 DI (w/ Spring Bean)

“IoC를 구현하기 위해 DI가 필요하다.”

  • 자바 빈

    : 자바프로그램이 관리하는 객체

  • 스프링 빈

    : 스프링이 컨테이너에 담아놓고 관리하는 객체

  • IoC (제어의 역전)

    : 프로그램 흐름의 제어권이 스프링에게 넘어간다.

    : 객체의 흐름을 제어하는 주체가 스프링에게 넘어간다.

    : 스프링 빈의 흐름을 제어하는 주체가 정반대로 바뀜 (스프링에게 넘어간다.)

  • 스프링 컨테이너 (a.k.a IoC, DI, 스프링 컨테이너)

    : 스프링 빈을 담아두는 공간

  • DI (의존성주입)

    : 우리는 의존성을 주입 당하는 역할.(스프링이 해준다)

    = 스프링은 의존성을 주입하는 역할

    [의존성을 주입해주려면 스프링 빈 (컨테이너 내부에있어야함) 이어야함 !]

    : @Configuration + @Bean [DI,IoC 모두의 역할이 될 수 있다 ]

    - 스프링아, 나 이거 스프링 빈으로 등록해줘 /ok, 스프링빈으로 생성해서 컨테이너에 등록해줄게

    : @Autowired - 스프링아, 여기에 의존성을 주입해줘 / ok, 거기에 주입해줄게 !

스프링 프레임워크의 장점?

IoC와 DI가 장점이다.

기존에는 개발자가 직접 객체의 생성과 소멸을 제어했는데, 스프링은 DI와 IoC로 인해 객체의 생성과 소멸 등 클래스 간의 의존관계를 스프링 컨테이너가 제어한다. 그러므로 클래스들 간의 의존관계가 낮아져서 클래스들의 변경이 자유로워 유지보수가 수월해진다는 장점이 있습니다.

🔗 참고한 URL

https://blogshine.tistory.com/551


Uploaded by N2T