• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 39

22 Apr 2019

Reading time ~4 minutes

Java EE 정리 39 - Spring DI, Spring Container


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
<beans>
    <bean id="">
    ...
</beans>
  • @Autowired, @Component
    • 구조가 간단하고 처리하는 일이 많지 않은 경우 사용
    • 소규모 Application, 단점은 어디서 의존성을 주입받는지 확인하기가 어렵다
    • 객체간의 의존성 주입상태를 한눈에 파악하기 어렵다

약결합

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

01

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

약결합 예

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

public interface Dao {
      public int insertEmp(EmpVO evo) throws SQLException;
      public List<EmpVO> selectEmp() throws SQLException;
}
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;
      }
}
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;
      }
}
public interface Service {
      public void addEmp(EmpVO evo);
      public List<EmpVO> searchEmp();
}
  • 인터페이스 Service를 구현한 ServiceImpl 클래스
    • 자식이 아닌 부모의 이름으로 객체를 저장하면 모든 자식을 받을 수 있다
      • == 객체 다형성
    • Service 객체는 업무를 처리하는데 반드시 Dao를 사용해야 한다
      • == Service는 DAO에 의존성이 있다
      • == Service객체를 사용하려면 DAO를 의존성 주입(DI)받아야 한다
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이 대신 수행해줌
      • 의존성 주입할 객체를 생성
      • 의존성 주입받을 객체를 생성하면서 의존성 주입
      • 의존성 주입받은 객체를 반환
/**
* 의존성 주입 관계를 설정하는 일
*/
public class Assembly {
      public Service getBean() {
            
            // 1. 의존성 주입할 객체를 생성
            Dao dao = new DAOOracleImpl();
            
            // 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
            Service service = new ServiceImpl(dao);
            
            // 3. 의존성 주입받은 객체를 반환
            return service;
      }
}
/**
* 조립자 클래스(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

  • 약결합이므로 DAO를 변경할 때 Service 내부를 고치는게 아니라 Assembly(조립자 클래스)만 고치면 됨
public class Assembly {
      public Service getBean() {
            
            // 1. 의존성 주입할 객체를 생성
            Dao dao = new DAOMySqlImpl();
            
            // 2. 의존성 주입받을 객체를 생성하면서 의존성 주입
            Service service = new ServiceImpl(dao);
            
            // 3. 의존성 주입받은 객체를 반환
            return service;
      }
}

03

  • Assembly가 하는 일을 Spring Container가 함

04

Spring Container

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

Spring Container 사용법

  • 설정용 XML 생성
    • 정의된 클래스는 사용여부에 상관없이 모두 객체가 생성된 상태에서 실행된다
    • 객체는 Singleton Pattern으로 생성된다
<!-- applicationContext.xml -->
<beans>
    <!-- 객체를 생성 -->
    <bean id="객체명" class="객체화할 클래스">
    ...
    <!-- 의존성 주입, 인터페이스가 없이 객체가 추가됨 -->
    <bean id="객체명" class="객체화할 클래스">
        <constructor-arg ref="의존성 주입할 객체명"/>
    </bean>
    ...
</beans>
  • Spring Container를 생성
ApplicationContext ac = new ClassPathXmlApplicationContext("설정용 xml");
  • 의존성 주입받은 객체를 얻는다
// 스프링 ~ 2.5.x, 캐스팅해서 사용
ServiceImpl si = (ServiceImpl)ac.getBean("beanId")
// 스프링 3.x 이상
ServiceImpl si = ac.getBean("beanId", "의존성주입받을클래스.class);
  • Spring Bean Configuration File 생성
    • Assembly의 일을 해줌

05

06

<!-- 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

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

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

09

10



Java EESpring