🤔 의존관계란?
- 하나의 모듈이나 컴포넌트에서 다른 모듈이나 컴포넌트를 참조하는 관계이다.
Ex)
CountryDao(interface)
,CountryServiceImpl(Service인터페이스를 상속받는 구현체)
라는 클래스가 있을 때,
CountryServiceImpl
는CountryDao
에 의존한다.
CountryServiceImpl 클래스 내부에서는
private CountryDao countryDao = CountryDaoImpl.;
🤔 의존성 주입이란❓
: 객체 간의 의존 관계를 외부에서 주입하는 방법
🤔 의존성 주입을 사용하는 이유 -> 결합도를 낮추기 위해
- 의존을 주입하는 객체가 바뀔경우 의존을 주입받는 객체의 코드도 수정해야 되므로 결합도가 높다고 할 수 있다.
그러나 Sping Container가 의존을 관리했을 경우, Spring Container가 의존을 주입하는 객체를 생성하고 필요한 곳에 매핑준다.
즉, 외부에서 객체가 생성 및 관리되기 때문에 의존관계의 결합도가 낮아질 수 있다.- 인터페이스를 사용하는 경우에 의존성 주입의 의미가 있다.
Bean
등록, 생성, 조회, 반환하는 기능 담당BeanFactory
를 바로 사용하지 않고 ApplicationContext
를 이용BeanFactory
를 확장한 IoC 컨테이너BeanFactory
가 제공하는 기능 + 부가 서비스 제공bean 생성 범위 지정 | 설명 |
---|---|
singleton | 스프링 컨테이너당 하나의 인스턴스(객체) 빈만 생성, (default scope) |
prototype | 컨테이너에 빈을 요청할 때마다 새로운 인스턴스(객체)를 생성 |
request | HTTP Request별로 새로운 인스턴스(객체) 생성 |
session | HTTP Session별로 새로운 인스턴스(객체) 생성 |
@Autowired
는 타입을 기준으로 해당 타입 또는 하위 타입의 bean을 주입한다.@Qualifire
Annotaion을 사용하여 명시적으로 bean을 지정한다. ```java
@Autowired
private CarDao carDao;
@Autowired
를 생략할 수 있다. @Autowired
public CarServiceImpl(CarDao carDao){
this.carDao = carDao;
}
public void setCarDao(CarDao carDao) {
this.carDao = carDao;
}
: 의존 관계 설정을 XML 파일로 하는 방법
Container에 객체를 등록 태그 : <bean>
<bean> 의 속성 | 설명 |
---|---|
id | spring container가 어떤 이름으로 class 객체를 가지고 있을 것인지 |
class | 어떤 클래스를 등록할 건지 |
scope | Bean 생성범위 지정 (defualt = singleton) |
의존성 주입 태그
의존성 주입 방법에 따라 사용하는 태그가 다르다.
생성자를 이용한 의존성 주입 방법에는 <constructor-arg>
태그를 사용
<constructor-arg> 의 속성 | 설명 |
---|---|
ref | 의존성을 주입 (bean객체를 주입) |
CountryServiceImp.java
// 생성자를 사용한 의존성 주입 방법 public CountryServiceImpl(CountryDao countryDao) { this.countryDao = countryDao; }
applicationConfig.xml
<!-- CountryServiceImpl 등록 --> <bean id="countryService" class="com.ssafy.model.service.CountryServiceImpl"> <!-- 객체를 생성하기 위해 생성자의 arg로 countryDao을 넣어줌 --> <constructor-arg ref="countryDao"></constructor-arg> </bean>
setter를 이용한 의존성 주입 방법에는 <property>
태그를 사용
<property> 의 속성 | 설명 |
---|---|
name | 의존성을 주입하려는 setter함수명에서 set을 빼고 앞의 대문자를 소문자로 바꾸기 |
ref | 의존성을 주입 (bean객체를 주입) |
vale | 문자열로 의존성을 주입 |
CountryServiceImp.java
public void setCountryDao(CountryDao countryDao) { this.countryDao = countryDao; }
applicationConfig.xml
<!-- CountryServiceImpl 등록 --> <bean id="countryService" class="com.ssafy.model.service.CountryServiceImpl"> <!-- ref는 bean의 id값 --> <property name="countryDao" ref="countryDao"></property> </bean>
applicationConfig.xml 전체코드
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- DBUtil 등록 -->
<bean id="dbUtil" class="com.ssafy.util.DBUtil"></bean>
<!-- CountryDaoImpl 등록 -->
<bean id="countryDao" class="com.ssafy.model.dao.CountryDaoImpl">
<constructor-arg ref="dbUtil"></constructor-arg> <!-- 객체를 생성하기 위해 생성자의 arg로 dbUtil을 넣어줌 -->
</bean>
<!-- CountryDaoImpl 등록 -->
<bean id="countryService" class="com.ssafy.model.service.CountryServiceImpl">
<!-- <constructor-arg ref="countryDao"></constructor-arg> --> <!-- 객체를 생성하기 위해 생성자의 arg로 countryDao을 넣어줌 -->
<property name="countryDao" ref="countryDao"></property> <!-- name은 setter의 set을 뺀 함수이름 ref는 bean의 id값 -->
</bean>
</beans>
Annotation을 이용해서 Bean 자동 등록
<beans>
에 xmlns:context="http://www.springframework.org/schema/context"
를 넣어 context를 사용할 수 있도록 import한 후
<context:component-scan base-package="com.ssafy.hello.di5"></context:component-scan>
를 넣으면 container가 선언된 Annotation을 보고 bean을 자동 등록해준다.
사용되는 annotation | 설명 |
---|---|
@Configuration | 설정 파일이라는 것을 알림 |
@Bean | Bean 생성 (name속성으로 bean객체의 이름을 지정가능) |
ApplicationConfig.java
@Configuration // 설정 파일이라는 것을 알림
public class ApplicationContifg {
//Bean 생성
// annotaion name속성으로 bean객체의 이름을 지정하지 않으면 자동으로 메소드 이름이 bean객체 이름이됨
@Bean(name="dbUtil")
public DBUtil dbUtil() {
return new DBUtil();
}
// bean객체 생성
@Bean
public CountryDaoImpl countryDaoImpl() {
// 의존성 주입
return new CountryDaoImpl(dbUtil());
}
@Bean
public CountryServiceImpl countryServiceImpl() {
return new CountryServiceImpl(countryDaoImpl());
}
}
Bean을 자동등록할 때 사용하여 해당 모듈이 Bean객체가 되어야 한다고 알리는 기능이다.
즉, 어떤 모듈을 등록할 것인지만 Annotation으로 지정해주면 container가 bean등록을 자동으로 해주기 때문에 ApplicationConfig에 직접 bean을 등록할 필요가 없다.
Annotation으로 알리기만 하면 bean을 자동 등록해주기 때문에 잘 쓰이는 방법이다.
가장 편리한 방법이지만 외부 모듈을 사용해야 할때 직접 외부 클래스에 접근할 수 없기 때문에
설정파일을 xml파일로 만들거나 java 클래스로 만들어야 한다.
Stereotype | 적용 대상 |
---|---|
@Repository | DAO(Data Access Layer) 또는 Repository 클래스에 사용 |
@Service | Service Layer의 클래스에 사용 |
@Controller | Presentation Layer의 MVC Controller에 사용 |
@Component | 위의 세가지에 해당되지 않는 클래스에 사용 |
ApplicationConfig.java
@Configuration // 설정 파일이라는 것을 알람
@ComponentScan(basePackages = "com.ssafy") // 스프링컨테이너가 만들어질 때 해당 패키지를 둘러보면서 bean(component)으로 등록(annotation을 보고)할 것들이 있으면 등록해줌
// bean등록하는 annotation : @Controller , @Controller , @Repository(dao), @Component(뒤의 3가지의 포함되지 않는 것들)
public class ApplicationContifg {
}