Spring_03.의존 관계

이혜민·2024년 8월 22일

spring

목록 보기
4/18

< 수업 순서 - 2024.08.22 >

1. Student : 학생정보를 저장하기 위한 클래스 - 학생정보 관련 값을 저장하기 위한 필드 및 기본 생성자, 메소드 작성

2. StudentApp : 출력 처리


3. 05-1_di.xml

⭐Spring Injection

: 스프링 컨테이너에 의해 Spring Bean으로 등록된 클래스로 객체를 생성할 때 객체 필드에 원하는 값(객체)이 저장되도록 설정하는 기능

→ 생성자(Constructor Injection) 또는 Setter 메소드(Setter Injection)를 사용해 객체 필드에 값(객체)을 저장

→ 스프링 컨테이너는 클래스의 기본 생성자를 사용해 객체 생성, 객체 필드에는 기본값(숫자형 : 0, 논리형 : false, 참조형 : null)이 저장

  • student1 : 객체 필드에 기본값이 저장 - 필드값을 변경하지 않았음.

- Constructor Injection : 생성자를 사용해 객체가 생성될 때 객체 필드에 값(객체)을 주입하는 방법

- constructor-arg : 생성자 매개변수에 값(객체)을 전달하기 위한 엘리먼트(엘리먼트 수 만큼 반드시 생성자 존재해야함)

- value 속성 : 생성자 매개변수에 전달되어 저장될 값(Value Injection : 값 주입 - 기본적으로 문자열 전달)

- type 속성 : 매개변수의 자료형

  • student2 : constructor-arg 엘리먼트로 생성자 매개변수에 int 값 전달

- index 속성 : 생성자 매개변수에 값(객체)을 전달하기 위한 순서(0부터 1씩 증가하는 정수값)

  • student3 : index 속성을 사용해 순서대로 값 전달

Setter Injection : Setter 메소드를 사용하여 객체 필드에 값(객체)을 주입하는 방법

- property 엘리먼트 : 필드의 Setter 메소드를 호출하여 필드값을 변경하는 엘리먼트

- name 속성 : 필드값을 변경할 필드의 이름

- value 속성 : Setter 메소드의 매개변수에 전달되어 저장될 값

  • student4 : property 엘리먼트를 사용해 setter 메소드를를 호출하여 name 속성에 필드명, value 속성에 저장할 값을 작성하여 값 전달

  • student5 : Constructor Injection과 Setter Injection을 함께 사용하여 객체 필드 초기화 처리

4. student.properties

  • student6 : PropertySourcesPlaceholderConfigurer 클래스를 사용해 Properties 파일에 저장된 값을 제공받아 Spring Bean Configuration File로 사용
    * properties 파일 : 값을 제공할 목적으로 작성된 파일


5. StudentDAO 인터페이스(부모) : 학생정보를 처리하는 DAO 클래스가 반드시 상속받아야 하는 인터페이스 → 객체간의 결합도를 낮춰 유지보수의 효율성 증가

6. StudentJdbcDAOImpl(자식) DAO 클래스 : DAO 클래스가 교체되어도 DAO 클래스를 사용하는 클래스(Service 클래스)에 영향을 최소화 하기 위해 반드시 인터페이스를 상속받아 작성하는 것을 권장 - 기본생성자, 인터페이스 메소드 오버라이드

7. StudentService 인터페이스 : 학생정보를 처리하는 Service 클래스가 반드시 상속받아야 하는 인터페이스

8. StudentServiceImpl : Service 클래스

  • Service 클래스 : 프로그램 실행에 필요한 데이터 처리 기능을 제공하기 위한 클래스 - 컴포넌트
    → Service 클래스의 메소드는 DAO 클래스의 객체로 다수의 메소드를 호출하여 작성 - DAO 모듈화
    → StudentDAO 인터페이스를 사용하여 필드 작성하여 StudentDAO 인터페이스를 상속받은 자식클래스의 객체를 제공받아 필드에 저장하여 의존관계 성립
    → 인터페이스로 필드 작성하여 DAO 클래스의 메소드를 사용하면 객체간의 결합도 감소

➡️ 설명 : StudentServiceImpl Service 클래스가 StudentDAO 인터페이스를 사용하여 필드를 작성하면 StudentDAO 인터페이스를 상속받은 StudentJdbcDAOImpl DAO 클래스의 메소드를 오버라이드 선언하고 호출 가능 - 오버라이드에 의한 다형성(결합도 ⬇️, 유지보수 효율성⬆️)

< 05-1_di.xml 파일 구체적 설명 >

  • 위와 같이 StudentDAO 인터페이스를 상속받은 자식클래스인 StudentJdbcDAOImpl 클래스를 Spring Bean으로 등록

  • StudentService 인터페이스를 상속받은 자식클래스인 StudentServiceImple 클래스를 Spring Bean으로 등록하는데 이렇게 등록하면 StudentServiceImpl 클래스의 studentDAO 필드에 [null]이 저장되므로 studentDAO 필드를 사용해 DAO 클래스의 메소드를 호출하면 NullPointerException이 발생
  • 해결법 : StudentServiceImpl 클래스의 studentDAO 필드에 StudentDAO 인터페이스를 상속받은 자식클래스인 StudentJdbcDAOImpl 클래스의 객체가 저장되도록 설정 - 의존관계 구현

⭐의존성 주입(Dependency Injection) : 스프링 컨테이너로부터 Spring Bean으로 등록된 클래스의 객체를 제공받아 필드에 저장되도록 주입

  • 방법 ① Constructor Injection : constructor-arg 엘리먼트를 사용해 StudentServiceImpl 클래스가 객체로 생성될 때 생성자 매개변수에 StudentJdbcDAOImpl 클래스의 객체를 전달받아 필드에 저장(=주입)
    → ref 속성 : 필드에 저장할 객체(Spring Bean)의 식별자(beanName)

  • 방법 ② Setter Injection : property 엘리먼트를 사용해 StudentServiceImpl 클래스가 객체로 생성된 후 Setter 메소드를 호출하여 StudentJdbcDAOImpl 클래스의 객체를 전달받아 필드에 저장

➡️ 설명 : Service 클래스(StudentServiceImpl)에서 사용하던 DAO 클래스(StudentJdbcDAOImpl)가 교체되어도 Service 클래스를 변경하지 않고 studentDAO에 저장되는 객체만 변경해도 객체와의 의존관계 변경 가능.
➡️ 위 코드와 같이 studentMybatisDAOImpl로 Spring Bean(객체)을 변경해주면 간단하게 객체와의 의존관계 변경 가능

Collection

9. Controller 인터페이스 : 추상메소드 작성

10. LoginController : Controller 인터페이스 상속받고 추상메소드 오버라이드

11. LogoutController : Controller 인터페이스 상속받고 추상메소드 오버라이드

12. ListController : Controller 인터페이스 상속받고 추상메소드 오버라이드

13. 05-2_collection.xml : Controller 인터페이스를 상속받은 자식클래스를 Spring Bean으로 등록

14. CollectionBean : Collection 클래스의 제네릭을 참조형 또는 인터페이스로 설정하여 Collection 객체에 값 또는 인터페이스를 상속받은 자식클래스의 객체를 요소로 추가하여 저장

1) 값 전달 : Set 객체는 set 엘리먼트, List 객체는 list 엘리먼트를 이용헤 필드에 저장. 값을 전달할 땐 하위 엘리먼트로 둘 다 value 속성 사용

2) 인터페이스를 상속받은 자식클래스의 객체 전달

① Set, List : set, list 엘리먼트 사용, Spring Bean으로 등록된 클래스의 객체를 전달받아 요소로 추가하기 위해 ref 엘리먼트 사용, bean 속성의 속성값으로 beanName 설정

② Map(Key, Value) : map 엘리먼트 사용, 하위 엘리먼트로 entry 엘리먼트로 Entry 추가, key 엘리먼트로 맵키 설정, ref 엘리먼트로 맵값 설정

③ Properties : props 엘리먼트 사용, 하위 엘리먼트로 prop을 사용하여 Entry 추가, key 속성으로 맵키 설정, prop 엘리먼트의 내용을 엔트리의 맵값으로 사용(클래스 경로를 맵값으로 작성)

15. CollectionBeanApp : ColletionBean 객체의 필드값을 반환받아 출력 처리

16. 05-3_autowire.xml

  • autowire 속성 : no(기본값), byName, byType, constructor 중 하나를 속성값으로 설정
    → Spribg Bean으로 등록된 클래스로 객체가 생성될 때 스프링 컨테이너가 자동 의존성 주입을 하기 위한 속성
    → no 속성값 : 자동 의존성 주입 X, 기본값이 no이므로 자동 의존성 주입이 되지 않아 Constructor 또는 Setter Injection을 사용해 필드에 객체가 저장되도록 의존성 주입
    → nyName 속성값 : 클래스의 필드명과 같은 이름의 식별자의 Spring Bean으로 객체를 제공받아 필드에 저장되도록 의존성 주입
    → byType 속성값 : 클래스의 필드와 같은 자료형(클래스)의 Spring Bean으로 객체를 제공받아 필드에 저장되도록 의존성 주입
    → constructor 속성값 : 클래스의 필드와 같은 자료형(클래스)의 Spring Bean으로 객체를 제공받아 필드에 저장되도록 의존성 주입

< 수업 순서 - 2024.08.23 >

⭐Annotation - 작성, 유지보수에 효율적

1. AnnotationStudentJdbcDAOImpl : StudentDAO 인터페이스 상속받음

2. AnnotationStudentServiceImpl : StudentService 인터페이스 상속받음

3. AnnotationStudentApp : 출력

4. 05-4_diAnnotation : bean 엘리먼트로 Spring Bean등록을 하지 않고 context Name Spaces를 사용하여 패키지 내에 있는 클래스(@Component 어노테이션)를 자동으로 Spring Bean 등록

  • Name Spaces : beans, context

  • context:componetn-scan 엘리먼트에 패키지 이름을 입력하면 패키지 내의 클래스를 Spring Bean으로 등록 가능

  • Spring Bean으로 등록하고자 하는 클래스에 @Component 어노테이션을 입력해주면 Sprring Bean으로 등록 가능

  • @Component : 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션

    • component 어노테이션은 클래스의 이름이 자동으로 식별자로 설정되기 때문에 value 속성을 사용하여 baeaName을 변경해줘야함
    • AnnotationStudentApp 클래스에서 아래와 같은 beanName으로 Bean 객체를 호출하였기 때문에 AnnotationStudentServiceImpl 클래스의 beanName을 같게 설정해줘야 호출 가능
  • @Repository : DAO 클래스(Repository 클래스)를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션

    • 트렌젝션 관리자에 의해 클래스의 메소드에 문제가 발생될 경우 롤백 처리 가능
  • @Service : Service 클래스를 스프링 컨테이너가 관리할 수 있는 Spring Bean으로 등록하기 위한 어노테이션

  • @AutoWired 어노테이션 : 스프링 컨테이너로부터 Spring Bean으로 등록된 클래스의 객체를 제공받아 필드에 자동으로 저장되도록 의존성 주입을 하기 위한 어노테이션

  • 필드가 여러개인 경우 필드마다 @AutoWired 어노테이션을 사용해 의존성 주입을 해줘야 함.

  • Setter Injection 기능을 사용하기 때문에 매개변수가 있는 생성자와 setter 메소드도 없어도 됨

5. AnnotationStudentMybatisDAOImpl

  • 문제점 : 필드의 자료형이 인터페이스인 경우 인터페이스를 삭송받은 자식클래스의 Spring Bean으로 2개 이상 등록된 경우 의존성 주입 실패 - 예외 발생

  • 해결법-1 : 이럴 경우 autowire 속성값을 [byName]으로 설정한 경우와 같은 방법으로 의존성 주입 : 다수의 클래스 중 의존성 주입하고자 하는 클래스의 식별자를 필드명과 동일하게 변경

    • AnntationStudentJdbcDAOImpl 객체를 studentDAO 필드에 저장하고자 할 때

    • AnntationStudentMybatisDAOImpl 객체를 studentDAO 필드에 저장하고자 할 때
  • 위와 같이 의존성 주입하고자 하는 클래스의 Component 어노테이션의 value 속성을 이용하여 beanName을 변경해서
    의존 관계 형성

  • 해결법-2 : @Primary 어노테이션 사용

    • 다수의 클래스 중 의존성 주입을 위한 클래스에 설정, Component 어노테이션보다 우선순위 높음
  • 해결법-3(권장) : 의존성 주입을 위한 필드에 @Qualifier 어노테이션 사용

    • value 속성을 사용하여 의존성 주입을 위한 객체 설정, 식별자의 클래스로 생성된 객체를 제공받아 필드에 저장
  • DAO 클래스를 변경하는 것(@Component, @Primary)보다 Service 클래스를 변경하는 것(@Qulifier)을 권장

우선순위 : @Qualifier > @Primary > @Component

0개의 댓글