DI란?
Dependency Injection, 즉 의존 주입이다. 의존 주입에 대해서 알아보기 전에 의존에 대해서 알아보자.
의존이란?
A객체가 B객체의 메서드를 실행하는 경우 A객체는 B객체에게 의존한다고 표현한다.
A객체가 B객체에게 메시지를 보내는 경우라고 생각하자.
B객체가 변경될 때 A객체도 변경된다면 A객체가 B객체에게 의존하는 것이다.
의존 주입을 해야하는 이유?
의존하는 객체를 직접 생성한다면 변경에 유연하게 대처할 수 없다.
예시를 통해 확인해보자.
public class Service {
private Dao dao = new MemberDao();
}
public class Service {
private Dao dao = new UserDao();
}
위와 같이 Dao객체를 직접 생성한다면 Dao 객체가 변경될 때 다음과 같이 Service 클래스를 변경해야한다.
하지만 의존 주입을 사용하면 코드의 변경이 줄어든다.
public class Service {
private final Dao dao;
public Service(Dao dao) {
this.dao = dao;
}
}
위처럼 변경한다면 dao 객체가 변경되어도 Service 내부를 변경할 필요가 없다.
물론, Service 객체를 생성하는 곳에서는 Service에 dao를 주입해주는 코드를 변경해야한다.
Dao dao = new MemnerDao();
Service service = new Service(dao);
// 실제 객체를 생성하는 곳이 수정된다.
// dao 객체가 변경되었을 때!
Dao dao = new UserDao(); // 이 부분만 변경하면 된다.
Service service = new Service(dao);
스프링에서는 위처럼 필요한 객체를 생성하고 주입하는 기능을 제공한다.
이것이 스프링 DI이다.
스프링은 어떻게 DI를 제공해주는 것일까?
예시를 통해 설정파일을 통해서 DI가 진행되는 과정을 알아보자
@Configuration
public class AppCtx {
@Bean
public Dao memberDao() {
return new MemberDao();
}
@Bean
public Dao userDao() {
return new UserDao();
}
@Bean
public MemberService memberService() {
return new MemberService(memberDao());
}
@Bean
public UserService userService() {
return new UserService(memberDao());
}
}
memberService() 와 userService() 는 파라미터로 동일한 메소드인 memberDao를 호출하였다.
그리고 다음과 같이 main을 실행해보았다.
public class Main {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);
MemberService memberService = ctx.getBean("memberService",MemberService.class);
MemberDao memberDao = ctx.getBean("memberDao", MemberDao.class);
System.out.println(memberService.getDao() == memberDao);
}
}
의존 객체들을 생성하고 주입해주는 과정은
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);
위의 코드가 실행될 때 진행되었다.
MemberService memberService = ctx.getBean("memberService",MemberService.class);
실행 시 디버깅을 통해 확인한 결과는 다음과 같다.
chapter2에서 보았던 singletonObjects를 확인해보았다.
확대해서 보면 다음과 같이 존재한다.
memberDao() 메소드를 통해 MemberDao 객체가 생성되었다. (MemberDao@2265)
그리고 UserService 객체 내부에, 위에서 생성되었던 MemberDao 객체(MemberDao@2265)가 주입되었다.
MemberService 객체 또한 같은 MemberDao 객체(MemberDao@2265)가 주입되었다.
정리
AppCtx 설정 클래스에서 미리 Bean 객체를 설정해주었으므로 스프링에서 MemberService와 UserService에 의존 주입을 진행할 수 있었다.
또한 스프링에서는 default로 Bean 객체를 싱글톤 객체로 만들기 때문에, memberDao() 메소드를 여러번 호출해도 항상 같은 객체를 반환함을 알 수 있었다.
따라서 MemberService와 UserService에 같은 memberDao 객체가 주입됨을 알 수 있다.
스프링이 DI를 제공하는 방식에는 여러가지가 있다. 위의 예시처럼 생성자를 통해 의존 객체를 주입할 수 있다.
그리고 setter 메서드를 통해 주입하는 방법이 있다.
'Spring' 카테고리의 다른 글
Bean 객체의 생성과 소멸 (0) | 2022.11.13 |
---|---|
@Component란? (0) | 2022.11.13 |
@Qualifier 알아보기 (0) | 2022.11.08 |
스프링이 Bean 객체를 관리하는 방법 (0) | 2022.11.06 |
댓글