2020년 7월 18일 토요일

Spring Framework Ioc 실습(XML 기반, 인터페이스, 세터주입)

2-2. Spring Ioc 실습(XML 기반, 인터페이스, 세터주입)

“오라클자바몰”이라는 회사를 만들어서 내가 잘아는 분야인 차를 팔기로 정했다. 차량의 구매는 현대자동차와 하고, 현대자동차에 “돈”을 지불하고 “차”를 받기로 했다.

STS

New à Project à Spring Legacy Project

Project Name : carmaker

Simple Projects : Simple Spring Maven

프로젝트 생성 후

- 프로젝트 루트아래의 pom.xml 파일을 오픈 후 스프링 버전을 4.2.0으로 변경

- src/main/java아래에서 “edu.biz.ioc” 패키지 생성

<!-- Spring -->

<spring-framework.version>4.2.0.RELEASE</spring-framework.version>

[Money.java]

package edu.biz.ioc;

public class Money {

private int amount;

public Money() {}

public Money(int amt) {

this.amount = amt;

}

public int getAmount() {

return this.amount;

}

public void setAmount(int amt) {

this.amount = amt;

}

}

[Car.java]

package edu.biz.ioc;

public class Car{

private String name;

public Car(String name) {

this.name = name;

}

public String getName() {

return this.name;

}

public void setName(String name) {

this.name = name;

}

}

[HyundaiMaker.java]

package edu.biz.ioc;

public class HyundaiMaker {

public HyundaiMaker () { } //생성자

public Car sell(Money money) {

System.out.println("I sold a car.");

Car car = new Car(“Sonata”);

return car;

}

}

[OrderManager.java]

package edu.biz.ioc;

public class OrderManager {

private HyundaiMaker maker;

public OrderManager () {

this.maker = new HyundaiMaker();

}

public void order() {

Car car = this.maker.sell(new Money(1000));

}

}

[src/main/rtesources/ioc.xml]

Project에서 마우스 우측버튼 -> new -> other -> Spring -> Spring Bean Configuration File

<?xml version="1.0" encoding="UTF-8"?>

<!—아래 부분만 코딩 하세요 à

<bean id="orderManager" class="edu.biz.ioc.OrderManager"/>

</beans>

[OrderManagerApp.java]

package edu.biz.ioc;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.xml.*;

import org.springframework.core.io.*;

public class OrderManagerApp {

public static void main(String[] args) {

BeanFactory factory =

new XmlBeanFactory(new FileSystemResource("src/main/resources/ioc.xml"));

OrderManager manager = (OrderManager)

factory.getBean("orderManager");

manager.order();

}

}

위 예제에서

ü OrderManager와 HyundaiMaker는 서로 떼어 놓을 방법이 없다. 이 두 클래스는 정적으로 결합(coupling)되어 있다

ü 하나의 버그를 고치면 그 결과 다른 새로운 버그가 생성되는 ‘두더지잡기(whack-a-mole)’ 버그를 만든다.

ü 다른 한편으로 완벽하게 분리된 코드는 아무일 도 못한다.

자바에서 결합도를 떨어뜨리는 일반적인 방법은 구현을 인터페이스 뒤로 숨기는 인터페이스 기반 프로그래밍을 하는 것이다. 이를 통해 클라이언트 클래스에 영향을 주지 않고도 쉽게 구현 클래스가 교체될 수 있도록 할 수 있다.

[CarMaker.java]

package edu.biz.ioc;

public interface CarMaker {

/** 돈을 받고 차를 판다. */

public Car sell(Money money) ;

}

[HyundaiMaker.java를 인터페이스를 구현하도록 수정]

package edu.biz.ioc;

public class HyundaiMaker implements CarMaker{

public HyundaiMaker() { }

public Car sell(Money money) {

System.out.println("I sold a car.");

Car car = new Car("Sonata");

return car;

}

}

[OrderManager.java 수정]

package edu.biz.ioc;

public class OrderManager {

//만약 인터페이스를 사용하지 않는다면 HyundaiMaker 다른 메이커로 교체된다

//면 아래의 private CarMaker maker를 포함하여 소스코드가 수정되어야 하지만

//인터페이스를 사용한다면 new HyundaiMaker () 부분만 수정하면 된다.

private CarMaker maker; //인터페이스 타입

public OrderManager() {

//인터페이스기반이므로 추후 DaewooMaker()로 수정 용이.

this.maker = new HyundaiMaker();}

public void order() {

Car car = this.maker.sell(new Money(1000));

}

}

ü 수정된 코드에 대한 검토

- 인터페이스 기반이므로 new HyundaiMaker 부분은 쉽게 다른 메이커로 변경 가능하지만 여전히 HyundaiMaker를 new 하고 있음. 강한 의존관계

- 자주 변경되는 구상클래스(Concrete class)에 의존하지 말라.

- 어떤 클래스를 상속받아야 한다면 , 기반 클래스를 추상 클래스 또는 인터페이스로 만들어서 구현하라.

- 어떤 클래스의 참조를 가져야 한다면 참조 대상이 되는 클래스를 추상 클래스, 인터페이스로 정의하라.

- 인터페이스를 만들어서 이 인터페이스에 의존하라. DIP(Dependency Inversion Principle)

[DaewooMaker.java]

package edu.biz.ioc;

public class DaewooMaker implements CarMaker {

public DaewooMaker () { }

public Car sell(Money money) {

System.out.println("I sold a car.");

Car car = new Car(“Tosca”);

return car;

}

}

[OrderManager.java 수정]

package edu.biz.ioc;

public class OrderManager {

private CarMaker maker;

public OrderManager(String name) {

this.maker = new DaewooMaker();

}

public void order() {

Car car = this.maker.sell(new Money(1000));

}

}

실행결과를 확인하여 DaewooMaker로 바뀐것을 확인하자.

인스턴스를 생성하는 방법의 문제를 해결하기 위해 스프링 프레임워크의 세터주입을 이용하자.

[OrderManager.java 수정]

public class OrderManager {

private String name;

private CarMaker maker;

public OrderManager() { }

public void order() {

Car car = this.maker.sell(new Money(1000));

}

//setter 메소드를 통해 CarMaker 타입 객체를 주입 받는다.

public void setMaker(CarMaker maker) {

this.maker = maker;

}

}

[ioc.xml 수정]

<?xml version="1.0" encoding="UTF-8"?>

<bean id="hyundaiMaker" class=" edu.biz.ioc.HyundaiMaker"/>

<bean id=“daewooMaker" class=" edu.biz.ioc.DaewooMaker"/>

<bean id="orderManager"

class="edu.biz.ioc.OrderManager">

<!-- 세터 주입을 의미 -->

<property name="maker">

<!-- 이부분을 수정하면 소스수정 없이 maker 교체 가능 -->

<ref bean="hyundaiMaker"/>

</property>

</bean>

</beans>

OrderManagerApp 실행 후 결과 확인하자.

Ioc.xml을 대신하여 자바 설정으로 변경해보자.

[MyConfig.java]

package edu.biz.ioc;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

@Configuration

@ComponentScan("edu.biz.ioc")

public class MyConfig {

@Bean

public CarMaker hyundaiMaker() {

return new HyundaiMaker();

}

@Bean

public CarMaker daewooMaker() {

return new DaewooMaker();

}

@Bean

public OrderManeger orderManager() {

OrderManager orderManager = new OrderManager();

orderManager.setMaker(this.hyundaiMaker());

return orderManager;

}

}

[OrderManagerApp.java]

package edu.biz.ioc;

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class OrderManagerApp {

public static void main(String[] args) {

// @Configuration 어노테이션이 적용된 클래스를 설정 정보로 이용하기 위해

// AnnotationConfigApplicationContext를 이용하면 된다.

ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

OrderManager manager = context.getBean(OrderManager.class);

manager.order();

}

}

스프링 프레임워크 Lazy-Loading, Pre-Loading

스프링에서 자바 빈을 로딩하는 방법은 BeanFactory를 이용 하는 방법과 ApplicationContext 를 이용하는 두가지 방법이 있다.

n Lazy-Loading

메소드나 클래스가 요청을 받는 시점에 자바빈의 인스턴스를 만들고 로딩하는 방법이다.

BeanFactory factory = new XmlBeanFactory( new InputStreamResource(

new FileInputStream(“ojc.xml"))); // 1

OracleJavaComm ojc = (OracleJavaComm) factory.getBean("oracleJavaBean"); // 2

1번에서 BeanFactory 컨테이너에 의해 ojc.xml 파일이 로드되더라도 어떠한 빈도 인스턴스화 되지 않고 2번에서 oracleJavaBean이 요청을 받는시점에 인스턴스화 되고 로드된다. 즉 getBean메소드 호출시 빈이 로드된다.

n Pre-loading

모든 빈들이 ApplicationContext 컨테이너에 의해 설정파일이 로드될 때 인스턴스로 만들어지고 로드 된다.

ApplicationContext context = new ClassPathXmlApplicationContext(“ojc.xml"); // 1

OracleJavaComm ojc = (OracleJavaComm) factory.getBean("oracleJavaBean"); // 2

1번에서 모든 싱글톤 빈들이 인스턴스화 된다. 그러므로 빈이 여러 개라면 시간이 소요될 것이다. 2번에서는 미리 컨테이너에서 만들어진 빈들이 클라이언트로 리턴된다.

스프링 설정파일에 여러개의 자바빈이 정의되었다고 모두 자주 사용되는 것은 아닐 수 있다. 모두 자주 사용되지 않을 수도 있으니 이러한 경우라면 요청이 있을 때 자바 빈을 인스턴스로 만드는 것이 좋을 것이다. 물론 모두 자주 사용되는 빈이라면 한번에 로드 하는 것도 좋은 방법이다.

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...