[Spring] IoC - DI 의존성 주입

SHINYEJI·2023년 10월 18일
0

Back-End

목록 보기
2/24

🤔 의존관계란?

  • 하나의 모듈이나 컴포넌트에서 다른 모듈이나 컴포넌트를 참조하는 관계이다.
    Ex)
    CountryDao(interface), CountryServiceImpl(Service인터페이스를 상속받는 구현체)라는 클래스가 있을 때,
    CountryServiceImplCountryDao에 의존한다.
    CountryServiceImpl 클래스 내부에서는
    private CountryDao countryDao = CountryDaoImpl.;

🤔 의존성 주입이란❓
: 객체 간의 의존 관계를 외부에서 주입하는 방법

🤔 의존성 주입을 사용하는 이유 -> 결합도를 낮추기 위해

  • 의존을 주입하는 객체가 바뀔경우 의존을 주입받는 객체의 코드도 수정해야 되므로 결합도가 높다고 할 수 있다.
    그러나 Sping Container가 의존을 관리했을 경우, Spring Container가 의존을 주입하는 객체를 생성하고 필요한 곳에 매핑준다.
    즉, 외부에서 객체가 생성 및 관리되기 때문에 의존관계의 결합도가 낮아질 수 있다.
  • 인터페이스를 사용하는 경우에 의존성 주입의 의미가 있다.

📌 DI(Dependency Injection); 의존성 주입

  • 유연하게 확장 가능한 객체를 만들어 두고 객체 간의 의존관계는 외부에서 동적으로 설정하는 것을 DI라고 한다.

🔴 Spring DI 용어

  • Bean
    • IoC방식으로 Spring container에 의해 생성, 구성, 관리 되는 Java 객체를 말한다.
  • BeanFactory
    • Spring이 IoC를 담당하는 핵심 컨테이너
    • Bean 등록, 생성, 조회, 반환하는 기능 담당
    • 일반적으로 BeanFactory를 바로 사용하지 않고 ApplicationContext를 이용
  • ApplicationContext
    • BeanFactory를 확장한 IoC 컨테이너
    • BeanFactory가 제공하는 기능 + 부가 서비스 제공

🔴 scope (Bean 생성범위)

bean 생성 범위 지정설명
singleton스프링 컨테이너당 하나의 인스턴스(객체) 빈만 생성, (default scope)
prototype컨테이너에 빈을 요청할 때마다 새로운 인스턴스(객체)를 생성
requestHTTP Request별로 새로운 인스턴스(객체) 생성
sessionHTTP Session별로 새로운 인스턴스(객체) 생성

🔴 의존성 주입 3가지 방법

  1. field : 순한참조때문에 잘 사용하지 않음
    • @Autowired는 타입을 기준으로 해당 타입 또는 하위 타입의 bean을 주입한다.
    • 같은 후보군 빈들이 여러개인 경우 @Qualifire Annotaion을 사용하여 명시적으로 bean을 지정한다.
      		```java
      		@Autowired
      		private CarDao carDao; 
  2. 생성자 : 권장하는 방법이다.
    • 생성자가 하나일땐 @Autowired를 생략할 수 있다.
     @Autowired   
     public CarServiceImpl(CarDao carDao){
    			this.carDao = carDao;
    		}
  3. setter : 실체 객체의 레퍼런스가 바뀔 수 있어 권장하지 않는다.
    public void setCarDao(CarDao carDao) {
    	this.carDao = carDao;
    }

🔴 설정(메타) 정보의 표현 방식 (의존관계 설정 방식)

  1. XML
  2. Annotation
  3. Java Code

1. XML

: 의존 관계 설정을 XML 파일로 하는 방법

  • Container에 객체를 등록 태그 : <bean>

    <bean>의 속성설명
    idspring container가 어떤 이름으로 class 객체를 가지고 있을 것인지
    class어떤 클래스를 등록할 건지
    scopeBean 생성범위 지정 (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을 자동 등록해준다.

2. Java Config

  • bean등록은 함수형태로 등록하고 해당 객체를 생성하여 반환한다.
  • 의존성은 함수형태로 주입한다.
사용되는 annotation설명
@Configuration설정 파일이라는 것을 알림
@BeanBean 생성 (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());
	}
}

3. Annotation

Annotation Bean 설정

  • Bean을 자동등록할 때 사용하여 해당 모듈이 Bean객체가 되어야 한다고 알리는 기능이다.

  • 즉, 어떤 모듈을 등록할 것인지만 Annotation으로 지정해주면 container가 bean등록을 자동으로 해주기 때문에 ApplicationConfig에 직접 bean을 등록할 필요가 없다.

  • Annotation으로 알리기만 하면 bean을 자동 등록해주기 때문에 잘 쓰이는 방법이다.

  • 가장 편리한 방법이지만 외부 모듈을 사용해야 할때 직접 외부 클래스에 접근할 수 없기 때문에
    설정파일을 xml파일로 만들거나 java 클래스로 만들어야 한다.

Stereotype적용 대상
@RepositoryDAO(Data Access Layer) 또는 Repository 클래스에 사용
@ServiceService Layer의 클래스에 사용
@ControllerPresentation 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 {
}

0개의 댓글