IoC(Inversion of Control) 제어의 역전
개발자가 직접 객체의 생성과 소멸 객체간 관계같은 객체의 제어를 수행하는 것이 아니라, 여러 프레임워크, 컨테이너에서 제어를 수행하는 것
DI(Dependency Injection) 의존성 주입
객체를 직접 생성하지 않고 외부에서 미리 만든 객체를 주입하는 것 → 클래스 간 결합을 느슨하게 해서 어떤 클래스의 변경이 그 클래스를 이용하는 다른 클래스에 미치는 영향을 줄인다.
- ⭐️⭐️⭐️생성자를 통한 주입(거의 이거 씀)
Consumer consumer = new Consumer(new Chicken()); 와 같이 생성자를 통해 주입
public class Consumer {
Food food;
public Consumer(Food food) {
this.food = food;
}
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer(new Chicken());
consumer.eat();
consumer = new Consumer(new Pizza());
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Pizza implements Food{
@Override
public void eat() {
System.out.println("피자를 먹는다.");
}
}
- 메서드를 통한 주입
consumer.setFood(new Chicken()); 와 같이 setFood 메서드로 주입
public class Consumer {
Food food;
void eat() {
this.food.eat();
}
public void setFood(Food food) {
this.food = food;
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.setFood(new Chicken());
consumer.eat();
consumer.setFood(new Pizza());
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Pizza implements Food{
@Override
public void eat() {
System.out.println("피자를 먹는다.");
}
}
- 필드에 직접 주입(잘 안 씀)
consumer.food = new Chicken();
public class Consumer {
Food food;
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.food = new Chicken();
consumer.eat();
consumer.food = new Pizza();
consumer.eat();
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Pizza implements Food{
@Override
public void eat() {
System.out.println("피자를 먹는다.");
}
}
- +) Lombok 사용
클래스 위에 @RequiredArgsConstructor를 달고 멤버 변수에 final을 달아준다.
@Component
@RequiredArgsConstructor // final로 선언된 멤버 변수를 파라미터로 사용하여 생성자를 자동으로 생성합니다.
public class MemoService {
private final MemoRepository memoRepository;
}
IoC Container
bean들을 모아둔 하나의 컨테이너
Bean
스프링이 관리하고 있는 객체, 이름은 클래스 명에서 첫 글자를 소문자로 바꾼 것으로 결정된다.
- 클래스 위에 @Component를 달면 bean으로 등록된다.
3 Layer Annotation
Controller, Service, Repository의 역할로 구분된 클래스들은 @Component 대신 각각
- @Controller, @RestController
- @Service
- @Repository
를 달아주면 된다.
- 객체의 의존성을 가지는 부분(객체를 주입 받는 부분)에 @Autowired를 달아준다. 생성자가 1개일 땐 생략 가능하다.
@RestController
@RequestMapping("/api")
public class MemoController {
private final MemoService memoService;
@Autowired
public MemoController(MemoService memoService) {
this.memoService = memoService;
}
....
}
위 코드에서 생성자는 MemoController(MemoService memoService) 하나이므로 @Autowired를 생략해도 된다.
'TIL > WEEK5' 카테고리의 다른 글
SpringBoot의 JPA (0) | 2023.06.15 |
---|---|
1주차 숙제 (0) | 2023.06.13 |
Spring 입문 1주차 (0) | 2023.06.12 |