개인 과제, spring 숙련
1. Ioc(Inversion of Control)
흔히 제어의 역전이라 불리는 것으로 메서드나 객체의 호출작업을 개발자가 결정하지 않고 외부에서 결정되는 것을 의미한다.
public class A {
private B b;
public A() {
b = new B();
}
}
기존에는 위와 같이 A는 B에 의존하고 있다는 것을 개발자가 명시해주어야 했다.
기존 객체 실행 단계
1. 객체 생성
2. 클래스 내부에서 의존성 객체 생성
3. 의존성 객체 메서드 호출
스프링에선 B 객체가 스프링 컨테이너에서 관리하는 Bean일 경우 @autowired
애너테이션으로 주입받을 수 있다.
public class A {
@Autowired
private B b;
}
스프링이 모든 의존성 객체를 스프링이 실행될때 만들고 필요한곳에 주입시켜줌으로써 Bean들은 싱글톤 패턴의 특징을 가진다.
제어의 흐름을 사용자가 컨트롤 하는 것이 아니라 스프링에게 맡겨 작업을 처리하게 되고, 이를 IoC 개념이라고 한다.
스프링의 객체 실행 단계
1. 객체 생성
2. 제어권을 가진 스프링이 의존성 객체를 만들어 주입
3. 의존성 객체 메서드 호출
당연히 이런 개념을 아무런 이유 없이 사용하진 않을 것이다.
IoC를 사용함으로써 얻는 장점은 아래와 같다.
2. DI(Dependency Injection)
스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, 객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다.
DI 패턴을 사용하여 IoC 설계 원칙을 구현하는 것으로 이해하면 된다.
<주입 예제>
필드를 통한 주입
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("피자를 먹는다.");
}
}
Food를 Consumer에 포함 시키고 Food에 필요한 객체를 주입받아 사용한다.
setter를 통한 주입
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("피자를 먹는다.");
}
}
set 메서드를 사용하여 필요한 객체를 주입받아 사용한다.
생성자 통한 주입(추천)
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("피자를 먹는다.");
}
}
생성자를 사용하여 필요한 객체를 주입받아 사용한다.
생성자를 통한 주입을 추천하는 이유