#DI
강한 결합이란?
- 다음과 같이 각각 새로운(new) 생성자를 만들어 구현하는 것.
- 문제점 : 일부 변경시 모든 코드를 다 수정해주어야 함 → 느슨한 결합을 지향
느슨한 결합
- 새로운 생성자를 만드는 것이 아니라 이미 생성된 객체를 가져다 씀!
- Repository에 객체 repository1를 만들고 Service는 이 객체를, 그리고 Controller는 이 service객체를 가져다 사용한다.
Class Service1 {
private final Repository1 repitory1;
// repository1 객체 사용
public Service1(Repository1 repository1) {
this.repository1 = new Repository1();
this.repository1 = repository1;
}
}
- 수정사항이 발생했을 때 하나만 변경해도 된다.
제어의 역전(IoC: Inversion of Controller)과 의존성 주입(DI: Dipendency Injection)
- 자신이 필요한 객체를 생성해서 사용하는 것이 아니라 용도에 맞게 필요한 객체를 그냥 가져다 사용하는 것 → DI(의존성 주입)
- 사용할 객체가 어떻게 만들어졌는지는 알 필요가 없다.
#스프링 IoC 컨테이너와 빈(Bean)
- 빈(Bean) : 스프링이 관리하는 객체
- 스프링 IoC 컨테이너 : '빈'을 모아둔 통
- 스프링 3계층 Annotation은 모두 @Component : @Controller, @RestController, @Service, @Repository
빈 등록방법
1. @Component
- @Component를 클래스 선언 위에 선언 → 스프링 서버가 뜰 때 객체를 생성하고 그 객체를 빈에 저장한다.
// 1. ProductService 객체 생성 ProductService productService = new ProductService(); // 2. 스프링 IoC 컨테이너에 빈 (productService) 저장 // productService -> 스프링 IoC 컨테이너
@Component public class ProductService { ... }
- 스프링 '빈'의 이름 : 클래스의 앞글자만 소문자로 변경한 것
- 빈 클래스에는 '빈'아이콘이 생성된다.
- Component 적용조건
- @ComponentScan에 설정해 준 packages 위치와 하위 packages들
- @SpringBootApplication에 의해 default가 설정되어 있다.
2. @Bean
- 직접 객체를 생성하여 빈으로 등록을 요청 → 스프링 서버가 뜰 때 스프링 IoC에 빈 저장
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfiguration {
@Bean
public ProductRepository productRepository() {
String dbUrl = "jdbc:h2:mem:springcoredb";
String dbId = "sa";
String dbPassword = "";
return new ProductRepository(dbUrl, dbId, dbPassword);
}
}
// 1. ProductService 객체 생성
ProductService productService = new ProductService();
// 2. 스프링 IoC 컨테이너에 빈 (productService) 저장
// productService -> 스프링 IoC 컨테이너
- 스프링 '빈'의 이름 : @Bean이 설정된 함수명
- 빈 클래스에는 '빈'아이콘이 생성된다.
빈 사용방법
1. @Autowired
- 맴버변수 선언 위에 @AutoWired → 스프링에 의해 DI됨
@Component public class ProductService { @Autowired private ProductRepository productRepository; // ... }
- 빈을 사용할 메소드 위에 @AutoWired → 스프링에 의해 DI됨
@Component public class ProductService { private final ProductRepository productRepository; @Autowired public ProductService(ProductRepository productRepository) { this.productRepository = productRepository; }
- @Autowired 적용조건
- 스프링 IoC컨테이너에 의해 관리되는 클래스에서만 가능
- @Autowired 생략조건
- Spring 4.3버전부터 생략가능
- 생성자 선언이 1개일 때만 생략가능
- Lombok의 @RequiredArgsConstructor
@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다. @RestController // JSON으로 데이터를 주고받음을 선언합니다. public class ProductController { private final ProductService productService; // 생략 가능 // @Autowired // public ProductController(ProductService productService) { // this.productService = productService; // } }
2. ApplicationContext
- 스프링 IoC 컨테이너에서 빈을 수동으로 가져오는 방법
@Component public class ProductService { private final ProductRepository productRepository; @Autowired public ProductService(ApplicationContext context) { // 1.'빈' 이름으로 가져오기 ProductRepository productRepository = (ProductRepository) context.getBean("productRepository"); // 2.'빈' 클래스 형식으로 가져오기 // ProductRepository productRepository = context.getBean(ProductRepository.class); this.productRepository = productRepository; } }
'서버 > Spring boot' 카테고리의 다른 글
#ORM, JPA, Spring data JPA, SQL (0) | 2022.02.05 |
---|---|
#Spring security (0) | 2022.01.28 |
#Spring MVC (0) | 2022.01.26 |
#H2연동하기 (0) | 2022.01.26 |
#Model과 ModelAndView (0) | 2022.01.26 |