---
title: "Java EE 정리 39"
date: "2019-04-22"
tags: ["Java EE","Spring"]
status: archived
verified: false
---

---

## Spring DI(Dependency Injection)

* **의존성 주입(이전명 = IoC, Inversion Of Control, 제어의 역행)**
* **약결합**
  * **기능의 조립과 분해가 쉬워지도록 만드는 것**
* **Spring core**
* **Spring Container들을 사용하여 객체가 생성되고 의존성 주입 설정**
  * **BeanFactory**
    * Bean들의 의존성 주입, 생명주기 관리
    * Bean은 Spring Framework가 객체를 생성해주는 클래스
  * **ApplicationContext(가장 많이 사용)**
    * Bean들의 의존성 주입, 생명주기 관리
    * 파일 관리, 국제화 기능
* **WebApplicationContext**
    * Bean들의 의존성 주입, 생명주기 관리
    * 파일 관리, 국제화 기능
    * Web에서 사용하는 기능
    * WebApplication당 하나만 사용되어야 한다
* **설정용 XML이 사용되거나 아니면 Annotation으로 설정**
* **설정용 XML**
  * **구조가 복잡한 대규모일 때 사용**
  * **객체간의 의존성 주입 관계를 한눈에 알 수 있다**
  * **applicationContext.xml**

```html
<beans>
    <bean id="">
    ...
</beans>
```

* **@Autowired, @Component**
  * **구조가 간단하고 처리하는 일이 많지 않은 경우 사용**
  * **소규모 Application, 단점은 어디서 의존성을 주입받는지 확인하기가 어렵다**
  * **객체간의 의존성 주입상태를 한눈에 파악하기 어렵다**

## 약결합

* **Interface로 구현**
  * **인터페이스를 사용하여 약결합을 구현, 객체간의 유연성을 높일 수 있다**

![01](/md/legacy-assets/javaEe/39/01.webp)

* **Assembly에서 Service를 생성할 때 사용할 DAO를 주입, UseAssembly에서는 getBean()을 이용하여 의존성 주입으로 생성된 Service를 반환받아 사용**

## 약결합 예

```java
package kr.co.sist.vo;
public class EmpVO {
      private int empno;
      private String ename;
...
```

```java
package kr.co.sist.dao;

public interface Dao {
      public int insertEmp(EmpVO evo) throws SQLException;
      public List<EmpVO> selectEmp() throws SQLException;
}
```

```java
public class DAOOracleImpl implements Dao {
      @Override
      public int insertEmp(EmpVO evo) throws SQLException {
            // Oracle DB에 insert 작업 수행
            System.out.println("Oracle에 사원정보 추가");
            return 1;
      }
      
      @Override
      public List<EmpVO> selectEmp() throws SQLException {
            List<EmpVO> list = new ArrayList<EmpVO>();
            
            list.add(new EmpVO(1111, "노진경"));
            list.add(new EmpVO(1112, "김희철"));
            list.add(new EmpVO(1113, "김정윤"));
            list.add(new EmpVO(1114, "이재찬"));
            
            return list;
      }
}
```

```java
public class DAOMySqlImpl implements Dao {
      @Override
      public int insertEmp(EmpVO evo) throws SQLException {
            // MySql DB에 insert 작업 수행
            System.out.println("MySql에 사원정보 추가");
            return 1;
      }
      
      @Override
      public List<EmpVO> selectEmp() throws SQLException {
            List<EmpVO> list = new ArrayList<EmpVO>();
            
            list.add(new EmpVO(2111, "오영근"));
            list.add(new EmpVO(2112, "공선의"));
            list.add(new EmpVO(2113, "이재현"));
            list.add(new EmpVO(2114, "이봉현"));
            
            return list;
      }
}
```

```java
public interface Service {
      public void addEmp(EmpVO evo);
      public List<EmpVO> searchEmp();
}
```


* **인터페이스 Service를 구현한 ServiceImpl 클래스**
  * **자식이 아닌 부모의 이름으로 객체를 저장하면 모든 자식을 받을 수 있다**
    * **== 객체 다형성**
  * **Service 객체는 업무를 처리하는데 반드시 Dao를 사용해야 한다**
    * **== Service는 DAO에 의존성이 있다**
    * **== Service객체를 사용하려면 DAO를 의존성 주입(DI)받아야 한다**

```java
public class ServiceImpl implements Service {
      
      private Dao dao;
      public ServiceImpl(Dao dao) { // 의존성 주입(DI)
            this.dao = dao;
      }
      
      @Override
      public void addEmp(EmpVO evo) {
            try {
                  // 업무로직을 처리
                  System.out.println("추가 작업에 대한 업무로직 처리");
                  dao.insertEmp(evo);
            } catch (SQLException e) {
                  e.printStackTrace();
            }
      }
      
      @Override
      public List<EmpVO> searchEmp() {
            List<EmpVO> list = null;
            try {
                  System.out.println("조회작업에 대한 업무로직 처리");
                  list = dao.selectEmp();
            } catch (SQLException e) {
                  e.printStackTrace();
            }
            
            return list;
      }
}
```



* **Assembly 클래스**
  * **의존성 주입 관계를 설정하는 일**
  * **Assembly의 일은 Spring Framework이 대신 수행해줌**
    * **의존성 주입할 객체를 생성**
    * **의존성 주입받을 객체를 생성하면서 의존성 주입**
    * **의존성 주입받은 객체를 반환**

```java
/**
* 의존성 주입 관계를 설정하는 일
*/
public class Assembly {
      public Service getBean() {
            
            // 1. 의존성 주입할 객체를 생성
            Dao dao = new DAOOracleImpl();
            
            // 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
            Service service = new ServiceImpl(dao);
            
            // 3. 의존성 주입받은 객체를 반환
            return service;
      }
}
```

```java
/**
* 조립자 클래스(Assembly)를 사용하여 서비스 객체를 얻고
* 서비스를 사용하는 일을 한다
*/
public class UseAssembly {
      
      public static void main(String[] args) {
            Assembly as = new Assembly();
            Service service = as.getBean();
            service.addEmp(new EmpVO(3111, "피카츄"));

            System.out.println("-----------------------");

            List<EmpVO> list = service.searchEmp();
            for(EmpVO emp : list) {
                  System.out.println(emp.getEmpno()+" /  "+emp.getEname());
            }
      }
}
```

![02](/md/legacy-assets/javaEe/39/02.webp)

* **약결합이므로 DAO를 변경할 때 Service 내부를 고치는게 아니라 Assembly(조립자 클래스)만 고치면 됨**

```java
public class Assembly {
      public Service getBean() {
            
            // 1. 의존성 주입할 객체를 생성
            Dao dao = new DAOMySqlImpl();
            
            // 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
            Service service = new ServiceImpl(dao);
            
            // 3. 의존성 주입받은 객체를 반환
            return service;
      }
}
```

![03](/md/legacy-assets/javaEe/39/03.webp)

* **Assembly가 하는 일을 Spring Container가 함**

![04](/md/legacy-assets/javaEe/39/04.webp)

## Spring Container

* **BeanFactory, ApplicationContext, WebApplicationContext**가 제공
* **객체간의 의존성 주입을 쉽게 해준다**
* **org.springframework.context package**에서 제공
* **의존성 주입의 정보는 설정용 xml에서 정의**
* **Spring Container가 생성하고 관리하는 클래스를 Bean이라고 한다**
* **Spring Container는 commons-logging.jar에 의존성이 있다**

## Spring Container 사용법

* **설정용 XML 생성**
  * **정의된 클래스는 사용여부에 상관없이 모두 객체가 생성된 상태에서 실행된다**
  * 객체는 **Singleton Pattern**으로 생성된다

```html
<!-- applicationContext.xml -->
<beans>
    <!-- 객체를 생성 -->
    <bean id="객체명" class="객체화할 클래스">
    ...
    <!-- 의존성 주입, 인터페이스가 없이 객체가 추가됨 -->
    <bean id="객체명" class="객체화할 클래스">
        <constructor-arg ref="의존성 주입할 객체명"/>
    </bean>
    ...
</beans>
```


* **Spring Container를 생성**

```java
ApplicationContext ac = new ClassPathXmlApplicationContext("설정용 xml");
```

* **의존성 주입받은 객체를 얻는다**

```java
// 스프링 ~ 2.5.x, 캐스팅해서 사용
ServiceImpl si = (ServiceImpl)ac.getBean("beanId")
```

```java
// 스프링 3.x 이상
ServiceImpl si = ac.getBean("beanId", "의존성주입받을클래스.class);
```

* **Spring Bean Configuration File 생성**
  * **Assembly의 일을 해줌**

![05](/md/legacy-assets/javaEe/39/05.webp)

![06](/md/legacy-assets/javaEe/39/06.webp)

```html
<!-- applicationContext.xml -->
...
<beans ...>
      <!-- 의존성 주입할 객체를 생성 -->
      <bean id="dao" class="kr.co.sist.dao.DAOOracleImpl"/>
      <bean id="my_sql" class="kr.co.sist.dao.DAOMySqlImpl"/>
      <!-- 의존성 주입받을 객체 생성 -->
      <bean id="service" class="kr.co.sist.service.ServiceImpl">
            <!-- 의존성 주입 -->
            <constructor-arg ref="dao"/>
      </bean>
</beans>
```

![07](/md/legacy-assets/javaEe/39/07.webp)

```java
public class UseSpringContainer {
      public static void main(String[] args) {
            
            // 1. 설정파일을 사용하여 Spring Container생성
            ApplicationContext ac = new  ClassPathXmlApplicationContext("kr/co/sist/di/applicationContext.xml");
            
            // 2. id를 사용하여 Bean(의존성 주입받은 객체) 얻기
            // ServiceImpl si = (ServiceImpl)ac.getBean("service");
            ServiceImpl si = ac.getBean("service",ServiceImpl.class);
            
            // 3. 찾아낸 Bean을 사용하여 출력
            si.addEmp(new EmpVO(3333, "김정윤"));
      
            List<EmpVO> list = si.searchEmp();
            for(EmpVO ev : list) {
                  System.out.println(ev.getEmpno()+"/"+ev.getEname());
            }
      }
}
```

![08](/md/legacy-assets/javaEe/39/08.webp)

* **common-logging**을 다운로드, 외부 라이브러리를 Build Path로 추가

![09](/md/legacy-assets/javaEe/39/09.webp)

![10](/md/legacy-assets/javaEe/39/10.webp)
