익명 객체란 ? 

익명 객체는 이름이 없는 객체를 말한다. 무명객체라고도 한다.

  • 사용 목적 : UI 이벤트 처리 객체 / 스레드 객체를 간편하게 생성하기 위해 많이 활용
  • 사용 용도 : 필드 / 로컬변수 의 초기값, 매개변수의 매개값으로 사용
  • 사용 조건 : 단독으로 생성 불가, 클래스 상속 or 인터페이스 구현해서 사용 가능 !
  • 재사용 목적이 아닌 1번만 사용 하려고 할 때 쓴다.

 

익명 자식 객체 생성

 

  • 부모 타입으로 필드나 변수를 선언하고, 자식 객체를 초기값으로 대입할 경우
  • 우선 부모 클래스를 상속해서 자식 클래스를 선언하고,
  • new 연산자를 이용해서 자식 객체를 생성한 후,
  • 필드나 로컬 변수에 대입하는 것이 기본이다.
class Child extends Parent { } // 자식 클래스 선언

class A
{
    Parent field = new Child(); // 필드에 자식 객체를 대입
    void method()
    {
    	Parent localVar = new Child(); // 로컬 변수에 자식 객체를 대입
    }
}

 

그러나 자식 클래스가 재사용되지 않고, 오로지 해당 필드와 변수의 초기값으로만 사용할 경우라면 익명 자식 객체를 생성해서 초기값으로 대입하는 것이 좋은 방법이다.

익명 자식 객체를 생성하는 방법을 다음과 같다. 주의할 점은 하나의 실행문이므로 끝에는 세미콜론(;)을 반드시 붙여야 한다.

 

Class A
{
    Parent field = new Parent()
    {
    	int childField;
        void childMethod() {}
        @Override
        void parentMethod() {}
    };
}

 

  • 아래 예제의 경우 부모클래스인 Parent를 상속해서 중괄호 { }; 와 같이 자식 클래스를 선언하라는 뜻
  • new 연산자는 이렇게 선언된 자식클래스를 객체로 생성한다.
  • 일반 클래스와의 차이점은 생성자를 선언할 수 없다는 것이다.
  • 메소드 내에서 로컬 변수를 선언할 때 초기값으로 익명 자식 객체를 생성해서 대입할 수도 있다.
  • 또한 메소드의 매개 변수가 부모 타입일 경우 메소드 호출 코드에서 익명 자식 객체를 생성해서 매개값으로 대입할 수도 있다.

 

public class B
{
	void method1(Parent parent) {}
	void method2()
	{
		method1(
		    new Parent()
		    {
		    	int childField;
		        void childMethod() {}
		        @Override
		        void parentMethod() {}
		    }
		);		
	}
}

 

  • 익명 자식 객체에 새롭게 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용되고, 외부에서는 필드와 메소드에 접근할 수 없다.
  • 왜냐하면 익명 자식 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용할 수 있기 때문이다.

 

익명 구현 객체 생성

 

 

  • 인터페이스(interface)에서 구현클래스를 명시적으로 선언하고 사용하는 이유는 재사용성이 높기 때문이다.
  • 그러나 쿠현 클래스가 재사용되지 않는다면 익명 구현 객체를 생성해서 사용하는 것이 인적 자원을 줄이는 좋은 방법이다.
  • 사용 예시는 아래를 참고 ! 

 

public class Button {
	
	OnClickListener listener;
	
	// 매개 변수의 다형성
	void setOnClickListener(OnClickListener listener)
	{
		this.listener = listener;
	}
	
	// 구현 객체의 onClock() 메소드 호출
	void touch()
	{
		listener.onClick();
	}
	
	// Nested interface
	interface OnClickListener
	{
		void onClick();
	}
	
}
public class Window {

	Button button1 = new Button();
	Button button2 = new Button();
	
	// 필드 초기값으로 대입
	Button.OnClickListener listener = new Button.OnClickListener() {
		
		@Override
		public void onClick() {
			System.out.println("전화를 겁니다.");
		}
	};
	
	Window() {
		button1.setOnClickListener(listener);
		button2.setOnClickListener(new Button.OnClickListener() {
			
			@Override
			public void onClick() {
				System.out.println("메세지를 보냅니다.");
			}
		});
	}
	
}
public class Main {

	public static void main(String[] args) {
		Window w = new Window();
		w.button1.touch();
		w.button2.touch();
	}
}

실행 결과는 아래와 같다.

 

 

 

 

익명 객체의 로컬 변수 사용

  • 익명 객체 내부에서는 바깥 클래스의 필드나 메소드는 제한 없이 사용할 수 있다.
  • 문제는 메소드의 매개 변수나 로컬 변수를 익명 개체에서 사용할 때이다.
  • 메소드 내에서 생성된 익명 객체는 메소드 실행이 끝나도 힙 메모리에 존재해서 계속 사용할 수 있다.
  • 매개 변수나 로컬 변수는 메소드 실행이 끝나면 스택 메모리에서 사라지기 때문에 익명 객체에서 사용할 수 없게 되므로 문제가 발생한다.
  • 이 문제에 대한 해결 방법은 로컬클래스의 사용제한과 비슷하다. (final 키워드 관련)
  • 익명 클래스의 내부 복사 위치에 신경 쓸 필요 없이 익명 객체에서 사용된 매개 변수와 로컬 변수는 모두 final 특성을 갖는다.

'Coding > Java' 카테고리의 다른 글

[28] JAVA 멀티스레드  (0) 2022.12.21
[27] JAVA 기초 복습  (0) 2022.12.14
[25] JAVA 중첩 클래스/ 중첩 인터페이스  (0) 2022.12.09
[24] JAVA 타입 변환과 다형성  (0) 2022.12.06
[23] JAVA 인터페이스  (0) 2022.12.04

중첩 클래스

    중첩클래스란(nested)?

  • 클래스 내부에 선언한 클래스를 의미한다.
  • 중첩 클래스를 사용하여 외부에 불필요한 클래스를 감춤으로써 코드의 복잡성을 줄일 수 있다.
  • 내부에 선언되는 위치에 따라 멤버 클래스로컬 클래스 두가지로 분류된다.

 

인스턴스 멤버 클래스

  • static 키워드 없이 중첩 선언된 클래스
  • 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 메소드는 선언할 수 없다.
  • 바깥클래스 외부에서 인스턴스 멤버 클래스의 객체를 생성하려면 먼저 바깥 클래스의 객체를 생성하고 다음에 인스턴스 멤버 클래스의 객체를 생성할 수 있다.

② 정적 멤버 클래스

  • static 키워드로 선언된 클래스
  • 바깥클래스 외부에서 정적 멤버 클래스 객체를 생성할 때 바깥클래스 객체를 먼저 생성할 필요 없이 생성이 가능하다.

③ 로컬 클래스

  • 메소드 내에 선언된 클래스이다.
  • 메소드 내부에서만 사용되므로 접근을 제한할 필요가 없기 때문에 접근 제한자 및 static을 붙이지 않는다.
  • 로컬 클래스 내부에는 인스턴스 필드와 메소드만 선언할 수 있고, 정적 필드와 메소드는 선언할 수 없다.
  • 로컬 클래스 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 한다.

 

중첩 클래스의 접근 제한

① 바깥 필드와 메소드에서 사용 제한

  • 바깥 클래스에서 인스턴스 멤버를 사용할 때 제한이 있다.
  • 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드의 초기값이나 인스턴스 메소드에서 객체를 생성할 수 있으나
  • 정적 필드의 초기값이나 정적 메소드에서는 객체를 생성할 수 없다.
  • 반면 정적 멤버 클래스는 모든 필드의 초기값이나 모든 메소드에서 객체를 생성할 수 있다.

② 멤버 클래스에서 사용 제한

  • 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 모든 메소드에 접근할 수 있지만
  • 정적 멤버 클래스 안에서는 바깥 클래스의 정적 필드와 메소드에만 접근할 수 있고 인스턴스 필드와 메소드에는 접근할 수 없다.

③ 로컬 클래스에서 사용 제한

  • 메소드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때 제한이 있다.
  • 로컬 클래스의 객체는 메소드의 실행이 종료되면 없어지는 것이 일반적 이지만, 로컬 스레드 객체를 사용할 때는 메소드가 종료되어도 계속 실행 상태로 존재할 수 있다.
  • 자바는 이 문제를 해결하기 위해 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때 final로 자동 선언한다.

④ 중첩 클래스에서 바깥 클래스 참조 얻기

  • 중첩 클래스에서 this키워드를 사용하면 바깥 클래스의 객체 참조가 아니라 중첩 클래스의 객체 참조가 된다.
  • 따라서 중첩 클래스 내부에서 바깥 클래스의 필드와 메소드를 접근하기 위해 다음과 같은 형식을 사용한다.
    • 바깥클래스.this.필드
    • 바깥클래스.this.메소드();

 

중첩 인터페이스

  • 클래스의 멤버로 선언된 인터페이스를 의미한다.
  • 클래스 내부에 선언되어 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만드는 역할이다.
  • 인스턴스 멤버 인터페이스와 정적(static) 멤버 인터페이스 모두 가능하다.
  • 주로 정적 멤버 인터페이스를 많이 사용하는데, UI 프로그래밍에서 이벤트를 처리할 목적으로 많이 활용 된다.

 

 

https://programmerbay.com/what-are-inner-class-nested-class-and-static-nested-class-in-java/

 

 

참고자료 : https://butter-shower.tistory.com/86

'Coding > Java' 카테고리의 다른 글

[27] JAVA 기초 복습  (0) 2022.12.14
[26] JAVA 익명 객체 (Anonymous)  (0) 2022.12.10
[24] JAVA 타입 변환과 다형성  (0) 2022.12.06
[23] JAVA 인터페이스  (0) 2022.12.04
[22] JAVA 추상클래스  (0) 2022.12.03

 

STEP 1 (다대일 단방향)

책 : 서점 = N : 1 이라고 가정하고 제출한 답안

package com.example.spring_week_2_test.entity;

import com.example.spring_week_2_test.dto.BookRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "Book") //테이블명 선언
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_id") //PK설정
    private Long id;

    @Column(nullable = false)
    private String author;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private int price;

    @Column(nullable = false)
    private Long quantity;

    @ManyToOne
    @JoinColumn(name = "book_store_id", nullable = false)
    private BookStore bookStore; //FK는 book_store_id 가 된다.


}
package com.example.spring_week_2_test.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "BookStore")
public class BookStore {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_store_id")
    private Long id;

    @Column(nullable = false)
    private String location;

    @Column(nullable = false)
    private String name;
}

 

STEP2 ( 다대일 양방향 )

 

책 : 서점 = N : 1 이라고 가정하고 제출한 답안

package com.example.spring_week_2_test.entity;

import com.example.spring_week_2_test.dto.BookRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "Book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_id")
    private Long id;

    @Column(nullable = false)
    private String author;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private int price;

    @Column(nullable = false)
    private Long quantity;

    @ManyToOne
    @JoinColumn(name = "book_store_id", nullable = false)
    private BookStore bookStore;

}

 

package com.example.spring_week_2_test.entity;

import com.example.spring_week_2_test.dto.BookStoreRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "BookStore")
public class BookStore {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_store_id")
    private Long id;

    @Column(nullable = false)
    private String location;

    @Column(nullable = false)
    private String name;

    @OneToMany(mappedBy = "bookStore")
    private List<Book> bookList = new ArrayList<>();

}

 

STEP3. 일대다 단방향 연관관계

 

 

책 : 회원 = N : 1 이라고 가정하고 제출한 답안

package com.example.spring_week_2_test.entity;

import com.example.spring_week_2_test.dto.BookStoreRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "BookStore")
public class BookStore {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_store_id")
    private Long id;

    @Column(nullable = false)
    private String location;

    @Column(nullable = false)
    private String name;

    @OneToMany(mappedBy = "bookStore")
    private List<Book> bookList = new ArrayList<>();

    @OneToMany
    @JoinColumn(name = "book_store_id")
    private List<Member> memberList = new ArrayList<>();

}
package com.example.spring_week_2_test.entity;

import jakarta.persistence.*;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Member")
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;

    @Column(nullable = false)
    private String address;

    @Column(nullable = false)
    private String email;

    @Column(nullable = false)
    private String nickname;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String phoneNumber;
}

 

 

STEP4. 구매(Purchase) Entity를 사용해서 (Member)과 책(Book)의 연관관계를 맺어보세요!

구매 : 회원 = N : 1

구매 : 책 = N : 1

이라고 가정하여 작성한 답안.

 

구매와 책 관계가 헷갈렸는데, 코드를 생각해보면 해당 책에 대한 코드는 하나일 것이고, 그 책에 대한 구매가 여러번 발생할 것으로 생각하면 이해가 조금 쉽다 ! 

package com.example.spring_week_2_test.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "Purchase")
public class Purchase {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "purchase_id")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    @ManyToOne
    @JoinColumn(name = "book_id")
    private Book book;

}
package com.example.spring_week_2_test.entity;

import com.example.spring_week_2_test.dto.BookRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "Book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "book_id")
    private Long id;

    @Column(nullable = false)
    private String author;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private int price;

    @Column(nullable = false)
    private long quantity;

    @ManyToOne
    @JoinColumn(name = "book_store_id", nullable = false)
    private BookStore bookStore;

    @OneToMany(mappedBy = "book")
    private List<Purchase> purchases = new ArrayList<>();
}
package com.example.spring_week_2_test.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Member")
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;

    @Column(nullable = false)
    private String address;

    @Column(nullable = false)
    private String email;

    @Column(nullable = false)
    private String nickname;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String phoneNumber;

    @OneToMany(mappedBy = "member")
    private List<Purchase> purchaseList = new ArrayList<>();

}

 

스텝 4 까지 했을 때 ERD

 

답안과 같은 양식인 것을 확인하고 제출 !

 

 

 

틀린 부분

1. Book Entity의 quantity 타입을 long 으로 했어야 하는데 Long 으로 작성했다.

2. STEP4 Purchase 부분 지연로딩 (fetch = FetchType.LAZY) 추가

 

package com.example.spring_week_2_test.entity;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@Table(name = "Purchase")
public class Purchase {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "purchase_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY) //(fetch = FetchType.LAZY) 추가
    @JoinColumn(name = "member_id") 
    private Member member;

    @ManyToOne(fetch = FetchType.LAZY) //(fetch = FetchType.LAZY) 추가
    @JoinColumn(name = "book_id") 
    private Book book;

}

참고 자료 : 

 

 

[JPA] 다양한 연관관계 매핑 (1) 다대일, 일대다

엔티티의 연관관계를 매핑할 때는 3가지를 고려해야한다. 다중성 단방향, 양방향 연관관계의 주인 먼저 두 엔티티가 일대일 관계일지 일대다 관계인지 다중성을 고려한다. 다음으로, 두 엔티티

jgrammer.tistory.com

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

[24] ERD(Entity Relationship Diagram)  (0) 2022.12.13
[23] Spring Security  (0) 2022.12.13
[21] ORM, JPA, Spring Data JPA  (0) 2022.12.08
[20] 의존성 주입 DI(Dependency Injection)  (0) 2022.12.08
[19] 스프링 프레임워크  (0) 2022.12.08

ORM, JPA, Spring Data JPA 

  • ORM : 객체(Object)와 관계형 데이터(Relational data) 를 매핑하기 위한 기술이다. 객체와 테이블 관계를 바탕으로 SQL문장을 자동으로 생성하여 객체로 DB를 조작하게 하는 기술.
  • JPA : 자바 ORM 기술에 대한 API 표준 명세이다. ORM을 사용하는 방식을 정의한 인터페이스를 모아둔 것. JPA는 특정 기능을 하는 라이브러리가 아니며, 말그대로 인터페이스이다. 따라서 사용방식에 대해서만 정의했을 뿐 구현이 없다.
  • Hibernate : JPA라는 명세의 구현체. 즉, JPA 인터페이스를 구현한 라이브러리 중 하나로 현 프레임워크 중 가장 주도 하고 있다.
  • Spring Data JPA : Spring Data JPA는 JPA를 쓰기 편하게 만들어놓은 모듈이다. JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공함으로써 JPA를 사용할 때 예상가능하고 반복적인 코드들을 대신 작성해주어 코드를 줄일 수 있도록 해준다.  

 

 ORM

  ORM 이란 Object-Relational Mapping 의 약자로, 이름 그대로 객체(Object)와 관계형 데이터(Relational data) 를 매핑하기 위한 기술이다. 즉, 내가 코드 상에서 생성한 객체가 DB상에 어떤 테이블과 연결이 된다는 것을 의미한다. 이러한 매핑이 필요한 이유는 객체 지향 언어과 관계형 데이터베이스사이의 패러다임 불일치가 있기때문이다.  이 둘 간의 패러다임 불일치 때문에 개발자는 더 많은 코드를 작성해야 하며, 이는 반복적이고 실수하기 쉬운 작업이 된다. 그렇기 때문에 개발자는 객체지향적인 설계에 집중할 수 없게 된다. ORM이 바로 이러한 문제를 해결해 준다. 

 

https://medium.com/@emccul13/object-relational-mapping-9d84807f5536

 

 패러다임 불일치

객체 지향 프로그래밍과 관계형 데이터베이스 사이의 데이터 표현 방식이 달라서 생기는 문제를 패러다임 불일치라고 한다. 패러다임 불일치가 일어나는 이유는 애초에 이들의 목표와 동작 방식이 다르기 때문이다.

  • 객체 지향
    • 필드와 메서드 등을 묶어서 객체로 잘 만들어 사용하는 것이 목표
    • 객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.
  • 관계형 데이터베이스
    • 데이터를 잘 정규화해서 보관하는 것이 목표

 

 

JPA

  JPA는 Java Persistence API의 약자로, 자바 ORM 기술에 대한 API 표준 명세이다. 즉, 인터페이스의 모음이다. 이러한 JPA 인터페이스를 구현한 대표적인 프레임워크가 하이버네이트(Hibernate)이다.JPA는 애플리케이션과 JDBC 사이에서 동작한다. 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하여 DB와 통신한다. 즉, 개발자가 직접 JDBC API를 쓸 필요가 없다.

 

 

 Hibernate

    JPA를 구현한 프레임워크 중 사실상 표준이다. 오픈소스 소프트웨어이다. 여기서 주목해야할 점은 JPA 기술 스펙이고 하이버네이트는  기능을 구현하여 공급해주는 역할이다.

 

Spring Data JPA

 Spring framework에서 JPA를 편리하게 사용할 수 있도록 지원하는 프로젝트(모듈)이다. Spring Data JPA의 목적은 JPA를 사용할 때 필수적으로 생성해야하나, 예상가능하고 반복적인 코드들을 대신 작성해줘서 코드를 줄여주는 것이다. 이는 JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공함으로써 이루어진다.

 Spring Data JPA는 JPA Provider이 아니다. 단지 데이터 계층에 접근하기 위해 필요한 뻔한 코드들의 사용을 줄여주도록 하는 인터페이스이다. 여기서 반드시 기억해야할 점은 Spring Data JPA 항상 하이버네이트와 같은 JPA provider 필요하다는 것이다.

 

 

출처 : 스프링부트와 aws로 혼자 구현하는 웹서비스(이동욱 저)

 

 

 

 

 

참고 자료 : https://doing7.tistory.com/105

스프링에서 DI (의존성 주입) 를 사용하는 이유

 

① DI(의존성 주입)이란?

  • DI란 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 다이나믹하게 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해준다.
  • 즉, 객체간의 의존성을 스프링 컨테이너(Spring Container)가 자동으로 연결해주는 것으로, 개발자가 빈(Bean) 설정파일에 의존관계가 필요한 정보를 추가해주면, 스프링 컨테이너가 자동적으로 연결해 준다
  • 의존성이란 한 객체가 다른 객체를 사용할 때 의존성이 있다고 한다.
  • 의존성 주입은 IoC(Inversion of Control: 제어의 역전)원칙 하에 객체 간의 결합을 약하게 해주고 유지보수가 좋은 코드를 만들어 준다. 또한 의존성 주입은 개발자들이 객체를 생성하는 번거로움과 다양한 케이스를 고려하는 겨우를 줄이고, 변수 사용과 개발에 더욱이 집중할 수있게 해준다.

* IoC 란?

  • IoC(Inversion of Control)란 "제어의 역전" 이라는 의미로, 말 그대로 메소드나 객체의 호출작업을 개발자가 결정하는 것이 아니라, 외부에서 결정되는 것을 의미한다.
  • 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여 가독성 및 코드 중복, 유지 보수를 편하게 할 수 있게 한다.
  • 스프링이 모든 의존성 객체를 스프링이 실행될때 다 만들어주고 필요한곳에 주입시켜줌으로써 Bean들은 싱글턴 패턴의 특징을 가지며, 제어의 흐름을 사용자가 컨트롤 하는 것이 아니라 스프링에게 맡겨 작업을 처리하게 된다.

흐름의 변화 상세 설명 

더보기

기존의 순서는 아래와 같았다.

1. 객체 생성
2. 의존성 객체 생성 (클래스 내부에서 생성)
3. 의존성 객체 메소드 호출

하지만, 스프링에서는 다음과 같은 순서로 객체가 만들어지고 실행된다.

1.객체 생성
2. 의존성 객체 주입 (스스로가 만드는것이 아니라 제어권을 스프링에게 위임하여 스프링이 만들어놓은 객체를 주입한다.)
3. 의존성 객체 메소드 호출

 

 

② DI(의존성 주입)를 사용하는 이유?

  1. 재사용성을 높여준다.
  2. 테스트에 용이하다.
  3. 코드를 단순화 시켜준다.
  4. 사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.
  5. 종속성이 감소하기 때문에 변경에 민감하지 않다.
  6. 결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.
  7. 객체간의 의존관계를 설정할 수 있다.

 

③ 스프링에서 의존성을 주입하는 방법

  • 생성자에서 주입
  • 필드에서 주입
  • setter 에서 주입

 

참고 자료 https://velog.io/@gillog/Spring-DIDependency-Injection

+ Recent posts