[Spring] MVC (DI, Dependency Injection)

Gabriela·2023년 10월 4일
0

Spring

목록 보기
5/8
post-thumbnail

DI

Dependency Injection


  • Spring Container에 저장된 객체가져오는 방식이다.

주요 Annotation


  • javax.inject.Inject
  • 타입(class)일치하는 객체를 찾아서 가져온다.
  • 동일한 타입(class)객체2개 이상 있다면 이름(id)이 일치하는 객체를 가져온다.
  • 타입(class)이름(id)이 일치하는 Bean이 없는 경우 오류발생한다.
  • 가져올 객체의 이름(id)을 지정하기 위해@Named(javax.inject.Named)사용할 수 있다.

필요한 디펜던시

<dependency>
	<groupId>javax.inject</groupId>
	<artifactId>javax.inject</artifactId>
	<version>1</version>
</dependency>

@Resource

  • javax.annotation.Resource
  • 이름(id)일치하는 객체를 찾아서 가져온다.
    - 동일한 이름(id)을 가진 객체없으면 오류발생한다.

필요한 디펜던시(Javax Annotation API)

<dependency>
	<groupId>javax.annotation</groupId>
	<artifactId>javax.annotation-api</artifactId>
	<version>1.3.2</version>
</dependency>

@Autowired

  • org.springframework.beans.factory.annotation.Autowired
  • @Inject 기반의 Spring Annotation이다. (타입 기반)
    • 타입(class)일치하는 객체를 찾아서 가져온다.
    • 동일한 타입(class)객체2개 이상 있다면 이름(id)이 일치하는 객체를 가져온다.
    • 타입(class)이름(id)일치하는 Bean이 없는 경우 오류발생한다.
  • 가져올 객체의 이름(id)지정하기 위해@Qualifier(org.springframework.beans.factory.annotation.Qualifier)사용할 수 있다.

DI 처리 방법


객체를 Spring Container에 넣는다.

(아래 3가지 방법 중 하나 이용)
  • <bean> 태그
  • @Configuration + @Bean
  • @Component
    • 클래스 레벨의 Annotation
    • @Component가 추가된 클래스는 자동으로 Spring Container에 객체저장된다.
    • Controller@ControllerService@ServiceDAO@Repository모두 @Component가지고 있다.

@Autowired

@Autowired를 이용해서 Spring Container에서 원하는 타입의 객체를 가져온다.

(아래 3가지 방법 중 하나 이용)
  • 필드에 주입하기
  • 생성자에 주입하기
  • Setter 형식의 메소드에 주입하기

@Autowired 사용 예시

  ┌-- Spring Container --┐
  │  BoardDto boardDto1  │
  │  BoardDto boardDto2  │
  └----------------------┘

필드에 주입하기

Field Injection

  • @Autowired명시된 필드Bean을 가져옴
  • 모든 필드마다 @Autowired명시해야 함
  • IoC Container생성된 Bean없어도 코드 작성 시 NULL 여부를 체크하지 않아서 위험할 수 있음
  • 코드 작성 시 순환 참조 여부미리 확인할 수 없음

활용 예제

    @Autowired
    private BoardDto boardDto1;  // Spring Container에 BoardDto 타입의 객체가 2개가 있으므로 이름이 일치하는 boardDto1 객체를 가져온다.
    @Autowired
    private BoardDto boardDto2;  // Spring Container에 BoardDto 타입의 객체가 2개가 있으므로 이름이 일치하는 boardDto2 객체를 가져온다.
   
    @Autowired
    @Qualifier(value="boardDto1")  // 가져올 객체 이름을 boardDto1으로 지정한다.
    private BoardDto b1;
   
    @Autowired
    @Qualifier(value="boardDto2")  // 가져올 객체 이름을 boardDto1으로 지정한다.
    private BoardDto b2;

Setter 형식의 메소드에 주입하기

Setter Injection

  • @Autowired명시된 세터매개변수Bean을 가져옴
  • 세터에 @Autowired한 번만 명시하면 모든 매개변수로 Bean을 가져오기 때문에 편리함
  • Field Injection처럼 IoC Container에 생성된 Bean이 없어도 코드 작성 시 NULL 여부를 체크하지 않아서 위험할 수 있음
  • 코드 작성 시 순환 참조 여부미리 확인할 수 없음

활용 예제

    private BoardDto boardDto1;
    private BoardDto boardDto2;
   
    @Autowired
    public void setBean(BoardDto boardDto1, BoardDto boardDto2) {  // Spring Container에 저장된 객체를 매개변수로 가져온다.
      this.boardDto1 = boardDto1;
      this.boardDto2 = boardDto2;
    }

생성자에 주입하기

Constructor Injection

  • 생성자(Generate constructor using field)를 만들면 생성자매개변수Bean을 가져옴
  • @Autowired명시할 필요가 없음

활용 예제

    private BoardDto boardDto1;
    private BoardDto boardDto2;
   
    @Autowired  // 스프링 4 이후 생략 가능
    public BoardController(BoardDto boardDto1, BoardDto boardDto2) {  // Spring Container에 저장된 객체를 매개변수로 가져온다.
      this.boardDto1 = boardDto1;
      this.boardDto2 = boardDto2;
    }

Constructor Injection 사용 권장

  • Constructor Injection에 잘못된 부분이 있는 경우 컴파일 오류가 발생함
  • 3가지 DI 방식 중 가장 안전한 방식

Controller의 Constructor Injection 예시


@Component

  • 클래스 레벨 애노테이션
  • @Component가 명시된 클래스자동으로 Bean으로 등록
  • @Component가 명시된 클래스를 찾기 위해서는 반드시 미리 컴포넌트를 찾을 위치를 등록해야 하는데,
    이를 Component Scan이라고 함
  • Spring Legacy Projectservlet-context.xmlComponent Scan이 등록되어 있어 별도의 설정이 필요 없고,
  • Spring Boot Project@SpringBootApplicationComponent Scan이 포함되어 있어 별도의 설정이 필요 없다.
  • 스프링에서 가장 권장하는 Bean 생성 방식이다.

Component Scan

@Component의 계층 구조


Component 주요 애노테이션

Annotation의미
@Component• 스테레오 타입의 최상의 객체
@Controller• 요청과 응답을 처리하는 Controller 클래스에서 사용
• Spring MVC 아키텍처에서 자동으로 Controller로 인식됨
@Service• 비즈니스 로직을 처리하는 Service 클래스에서 사용
• Service Interface를 구현하는 ServiceImpl 클래스에서 사용
@Repository• 데이터베이스 접근 객체(DAO)에서 사용
• 데이터베이스 처리 과정에서 발생하는 예외를 변환해주는 기능을 포함함

필드에 final 처리

  • 보안 문제를 방지
  • final field의 값은 반드시 채워줘야 한다.
  • field에 final 처리 시 생성자만 사용 가능해진다.
  • 생성자 @Autowired는 스프링 버전4 이상부터 생략이 가능하다.
  • 생성자Lombok Annotation으로 대체 가능하다.

Lombok

  • @RequiredArgsConstructor : final field 전용 생성자 Annotation(필수주입)
  • 오류발생 여부 처리 유무의 존재만 다를 뿐 @AllArgsConstructor와 동일하게 사용 가능하다.

‣ 짚어보기

  • @Autowired@Inject스프링화 라고 볼 수 있다.
  • @Component : 직접 만든 클래스사용하는게 편리하고, 가져오는 것들(만들어져 있는 클래스들)은 객체화 시킬 때
    (1) <bean> 태그
    (2) @Configuration + @Bean
    (3) @Component
    방식을 사용

순서

  • 스프링 컨테이너에 담아두기(저장) 👉 Component
  • 스프링 컨테이너에서 가지고 오기 👉 Autowired
  • 생성자Setter@Autowired를 붙여서 작동하는 방식: 실제로는 매개변수주입된다.
  • 월컴 페이지를 담당하는 Controller실제 기능을 담당하는 Controller따로 생성하기

고정주소 처리

  • 공통된 매핑값이 반복될 때 처리하는 방법

  • @RequestMapping() 메소드
  • 클래스 레벨 Annotation
  • 공통된 Mapping 값이 모든 메소드에서 반복으로 요청될 때 사용한다.
  • 해당 값이 모든 메소드요청자동으로 삽입된다.
  • value만 있을때 value=는 생략 가능하다.
예)
// "/blog"로 시작하는 요청을 처리하는 컨트롤러가 된다.
@RequestMapping("/blog")  // == @RequestMapping(value="/blog")

profile
개발이 세상에서 제일 재밌어요

0개의 댓글