본문 바로가기
Spring Framework/Spring

DI 정리

by 도쿠니 2022. 6. 6.

스프링 컨테이너 생성 및 종료

  • ApplicationContext 인터페이스 이용
  • 자주 사용하는 구현체
    • AnnotationConfigApplicationContext : 어노테이션 이용방식
    • GenericXmlApplicationContext : XML 이용방식
  • 컨테이너에 두 개 이상의 설정 파일 등록 방법
    • 사용하고자 하는 설정 파일들을 매개변수로 전달
    • 하나의 설정 파일에 다른 파일들을 @Import 로 가져오기
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main{
	public static void main(String[]args) {

		// 스프링 컨테이너 생성
           		// 매개변수로 여러 개의 설정파일을 컨테이너에 등록할 수 있다.
		AnnotationConfigApplicationContext context = 
           	 	new AnnotationConfigApplicationContext(AppConfig.class,Appconfig2.class);
		// 컨테이너 종료
		context.close();
	}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

// 설정파일은 @Configuration 으로 표시
@Configuration
// @Import의 값으로 {} 배열을 전달하면 AppConfig만 등록해도 3,4도 같이 등록된다.
@Import({AppConfig3.class,AppCofig4.class})
public class AppConfig{}

Bean 관련

Bean 호출

  • ApplicationContext.getBean(Bean name, Bean type)
    • Bean type만으로도 호출가능
      • 동일한 타입이 2개 이상일 경우, Exception 발생
      • 이름으로 명확하게 호출해주는 것이 좋음
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main{
	public static void main(String[]args) {

		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    		Hello hello = context.getBean("hello", Hello.class);
	}
}

Bean 등록

  • @Bean
    • @Configuration 클래스(설정 파일)에서 사용
    • 속성값으로 빈 이름을 등록할 수 있다.
    • 아무것도 주지않으면 메소드 명이 빈 이름으로 등록된다.
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AppConfig{
    
    	// 빈 이름이 hi
    	// @Bean 만 사용하면 메소드 명이 빈 이름이 된다.
    	// 메소드명(빈이름)은 보통 클래스명에서 맨 앞글자를 소문자로 바꾼 것을 사용한다.
    	@Bean("hi")
    	public Hello hello() {
    		return new Hello();
    	}
    }
  • @Component
    • Bean으로 등록할 클래스에 어노테이션 추가
    • 이 방식을 사용하려면 Component Scan이 필요
    • @Controller, @Service, @Repository 등도 같은 역할을 한다.
    import org.springframework.stereotype.Component;
    
    @Component
    public class Hello{}
    

Component Scan

  • @Component 방식으로 빈등록을 하기 위한 방법
  • 설정 파일에 @ComponentScan 추가
  • 스캔 범위 설정
    • basePackages 속성
      • 해당 패키지와 하위 패키지에 속한 모든 클래스 스캔
    • basePackgeClasses 속성
      • 해당 클래스가 위치한 패키지 및 하위 패키지에 속한 모든 클래스 스캔
  • 스캔 대상 제외하거나 포함하기
    • includeFilters 속성
    • excludeFilters 속성
      • 예시 : excludeFilters = @Filter(type= FilterType.REGEX, pattern = “정규표현식”)
      • type 종류
        • REGEX
          • 정규표현식 사용
        • ASPECTJ
        • ANNOTATION
          • 특정 어노테이션 붙인 클래스 제외
        • ASSIGNABLE_TYPE
          • 특정 타입이나 하위 타입을 제외
package com.example.spring_study;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages ={"com.example.spring_study"})
public class AppConfig{}
  • 빈 수동등록(@Bean) vs 자동등록 (@Component)
    • 수동등록이 우선한다.

DI 관련

DI 방식

  • 생성자 방식
    • 생성자를 통해 객체를 생성할 때 의존성 주입
    • 참고로 스프링 개발팀에서는 생성자 주입을 하는 것을 추천한다.
  • Setter 방식
    • 객체 생성 후, Setter로 의존성 주입
  • 필드 주입 방식
    • @Autowired로 필드에 바로 의존성 주입

의존 자동 주입

  • @Autowired 사용 (스프링 제공, 타입기반 매칭)
    • @Resource (자바 제공,이름 기반 매칭) , @Inject (자바EE 제공) 도 같은 역할
    • 보통 필드메소드에 사용하고 생성자에도 사용 가능
    • 메서드에 붙이면 메서드 파라미터 타입에 해당하는 빈 객체를 주입
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class World{
    	// 필드 주입 방식
    	@Autowired
    	private Hello hello;
    	
    	void print(){this.hello.print();}
    }
  • 생성자를 통한 자동 주입
    • 단일 생성자의 경우, 빈 등록시 생성자의 매개변수인 빈들이 자동으로 주입된다.
    • 다중 생성자의 경우, @Autowired를 생성자에 붙여주어야한다.
    • 생성자로 의존성 주입하면 final 키워드를 사용할 수 있어서 안전하다.
      • 롬복의 @RequiredArgsConstructor를 사용하면 편리하게 생성자로 DI할 수 있다.
      @Component
      @RequiredArgsConstructor
      public class Hello {
          private final World world;
      }
      
  • @Autowired빈 조회 전략
    1. 타입 조회
    2. 동일한 타입이 여러 개면 이름으로 조회
  • 타입도 동일하고 이름도 동일한 빈이 두개 이상일 때
    • @Qualifier
      • 사용할 빈과 해당 빈을 주입할 곳에 동일한 @Qualifier("beanName”)을 붙인다.
      • 이름은 클래스 명의 카멜케이스로 해주는게 좋다.
    • @Primary
      • 해당 어노테이션이 붙은 빈을 최우선으로 주입한다.
    • Set 또는 List 동일한 빈 모두 받기
      • 모든 동일한 빈을 Set이나 List 자료구조로 받아 선택해서 사용할 수 있도록 한다.
    • 프로퍼티 이름을 빈과 동일하게 하기
      • 중복되지 않도록 프로퍼티 이름(메소드명,필드명,매개변수명 등)을 해당 빈과 동일하게 맞춘다.
      • 되도록이면 이렇게 사용하자.
  • @Autowired 필수 여부
    • 자동 주입은 매칭되는 빈이 없으면 예외를 발생시킨다.
    • 매칭되는 빈이 없더라도 예외 발생없이 처리하고 싶다면 아래와 같은 설정을 해야한다.
    • @Autowired(required = false)
      • 매칭되는 빈이 없으면 자동 주입 자체를 하지 않아서 익셉션이 발생되지 않음
      • 매칭되는 빈이 없으면 메서드 자체를 호출하지 않음. → null 을 주입하지 않는다.
    • Optional<빈 타입>
      • 자동 주입 대상 타입이 Optional 일 경우, 일치하는 빈이 존재하지 않으면 값이 없는 Optional을 인자로 전달하고 익셉션 발생 X
      • 일치하는 빈이 있으면 값이 있는 Optional 전달
    • @Nullable
      • 해당하는 빈이 없으면 null 전달, 익셉션 발생 X
  • 수동 주입 vs 자동 주입(@Autowired)
    • 자동 주입이 우선인데 수동,자동 섞이면 에러 발생시 찾기어려우니 일관성있게 하나만 사용하자.

빈 생명주기(Life Cycle)범위(Scope)

스프링 컨테이너의 라이프사이클

  • 초기화
    • 빈 객체 생성 → 의존 주입 → 초기화
  • 종료
    • 빈 객체 소멸

빈의 생명주기

  • 컨테이너가 빈 객체의 라이프사이클을 관리
  • 객체 생성 → 의존 설정 → 초기화 → 소멸
  • 객체가 초기화 되고 소멸할 때 특정한 메소드를 호출하려면 아래와
    • 초기화 시 실행할 메소드 설정
      • 빈에 InitialiazingBean 인터페이스 구현
        • afterPropertiesSet()
      • @Bean(initMethod = “메소드명”)
      • 빈 메소드에 @PostConstruct 추가
        • Deprecated 되었다.
    • 소멸 시 실행할 메소드 설정
      • 빈에 DisposableBean 인터페이스 구현
        • destroy()
      • @Bean(destroyMethod = “메소드명”)
      • 빈 메소드에 @PreDestroy 추가
        • Deprecated 되었다.

범위

  • 빈은 기본적으로 Singleton 범위를 가진다.
  • 범위를 변경하고 싶으면 @Scope 을 사용
    • 범위 종류
      • Singleton : 기본 값, 하나의 객체만을 생성해서 관리
      • Prototype : 매번 새로운 객체를 생성, 컨테이너 종료 시 같이 소멸되지 않기 때문에 따로 소멸시켜주어야 한다.

스프링의 환경 설정

  • 특정한 환경에서만 동작하는 Bean을 만들 때 @Profile 사용
  • 실행 환경변수를 통해서 특정 환경을 조성할 수 있다.
    • 인텔리제이 기준, 실행 환경에서 환경변수에 spring.profiles.active=ProfileName
  • 클래스 단위에 적용하거나 메서드 단위에 적용 가능 
    • 클래스 단위
      • @Configuration @Profile(”test”)
      • @Component @Profile(”test”)
    • 메서드 단위
      • @Bean @Profile(”test”)

'Spring Framework > Spring' 카테고리의 다른 글

Spring Validation  (0) 2022.06.07
Data Binding  (0) 2022.06.07
Spring AOP(관점 지향 프로그래밍)  (0) 2022.06.07
Spring Framework 소개  (0) 2022.06.05
Spring 등장 배경  (0) 2022.06.02

댓글