[Spring] 스프링으로 계산기 만들기

0. 출처

아직 배우고 있는 중이라 부정확한 정보가 포함되어 있을 수 있습니다!
주의하세요!

올인원 스프링 프레임워크 참고.

https://search.shopping.naver.com/book/catalog/41101295635?cat_id=50010920&frm=PBOKPRO&query=%EC%98%AC%EC%9D%B8%EC%9B%90+%EC%8A%A4%ED%94%84%EB%A7%81+%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC&NaPm=ct=lma2t8xk%7Cci=a48cf03f14ef65da3f75709822c7b195a41bd691%7Ctr=boknx%7Csn=95694%7Chk=dba64f780dac99af3b6dc40908ddb18778aaa3a1


1.디렉터리 구조

  • [project_name]/src/main/java : .java 파일 관리.
  • [project_name]/src/main/resources : 자원 관리. 스프링 설정 파일(xml) 또는 프로퍼티 파일.
  • pom.xml : 메이븐 설정 파일


가. 메인 리포지터리

또는 remote repository라고 한다.

필요한 모듈들을 다운로드하는 곳이다.

https://mvnrepository.com이 우리가 사용하는 메인 리포지터리의 주소다.

다운로드하여서 사용할 수 있는 다양한 Artifact(모듈)들이 있다.

pom.xml을 통해서 모듈을 다운로드할 수 있다.

apache 재단에서 관리한다. (maven이 apache 재단에서 호스팅 한다.)


나. 로컬 리포지터리

메인 리포지터리에서 다운로드한 라이브러리(.jar)가 설치되는 디렉터리.

//default location of local repository
${user. home}/. m2/repository/

//윈도우의 로컬 리포지터리 경로
C:\Users\<User_Name>\.m2\repository\

//리눅스의 로컬 리포지터리 경로
/home/<User_Name>/.m2
//또는
~/.m2

//맥의 로컬 리포지터리 경로
/Users/<user_name>/.m2
//또는
~/.m2
Code language: PHP (php)

한 번 설치한 모듈은 재사용된다.


다. 프로젝트 빌드 설정

<!-- pom.xml -->
...
<!-- bulid config -->
  <build>
      <plugins>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.11.0</version>
              <configuration>
                  <source>11</source>
                  <target>11</target>
                  <encoding>utf-8</encoding>
              </configuration>
          </plugin>
      </plugins>
  </build>
Code language: HTML, XML (xml)
  • <source>11</source> : java 소스 코드의 버전. 여기선 java 11의 문법과 API를 사용하여 코드를 컴파일함.
  • <target>11</target> : 바이트 코드의 버전을 의미함. 여기선 java 11 버전의 JVM에서 실행될 것임을 의미한다.
  • <encoding>utf-8</encoding> : 소스 코드의 인코딩 설정. Maven 컴파일러가 소스 코드를 읽을 때 utf-8로 읽도록 지시함.

2. 스프링으로 계산기 만들기

가. MainClass.java

package ch03_calc_01;
import org.springframework.context.support.GenericXmlApplicationContext;

public class MainClass {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationContext.xml");

        CalAssembler calAssembler = ctx.getBean("calAssembler", CalAssembler.class);
        calAssembler.assembler();

        ctx.close();
    }

}
Code language: JavaScript (javascript)

IoC 컨테이너에서부터 calAssembler bean을 받아온다.

이때 가져올 뿐 calAssembler bean을 가져오기 위해서 어떠한 값도 전달하지 않는다.


나. CalAssembler.java

package ch03_calc_01;

public class CalAssembler {

    MyCalculator calculator;
    CalAdd calAdd;
    CalSub calSub;
    CalMul calMul;
    CalDiv calDiv;

    public CalAssembler(MyCalculator calculator, CalAdd calAdd, CalSub calSub, CalMul calMul, CalDiv calDiv) {
        this.calculator = calculator;
        this.calAdd = calAdd;
        this.calSub = calSub;
        this.calMul = calMul;
        this.calDiv = calDiv;
    }

    public void assembler() {
        calculator.calculate(10,5,calAdd);
        calculator.calculate(10,5,calSub);
        calculator.calculate(10,5,calMul);
        calculator.calculate(10,5,calDiv);
    }
}
Code language: JavaScript (javascript)

스프링 사용 이전과 비교해 보자.

//스프링 사용 이전
    public CalAssembler(){
        calculator = new MyCalculator();
        calAdd = new CalAdd();
        calSub = new CalSub();
        calMul = new CalMul();
        calDiv = new CalDiv();

        assemble();
    }
Code language: PHP (php)

CalAssembler의 생성자에서 더 이상 MyCalculator, CalAdd, CalSub, CalMul, CalDiv 객체를 생성하지 않는다.

하지만 앞선 MainClass에서도 CalAssembler를 사용할 때 MyCalculator, CalAdd, CalSub, CalMul, CalDiv을 전달해주지 않았다.

그러면 언제, 누가 MyCalculator, CalAdd, CalSub, CalMul, CalDiv를 전달해 주었을까?


다. applicationContext.xml

<!-- applicationContext.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">

    <!-- <bean id="tWalk" class="ch03_pjt_02.TransportationWalk" /> -->
    <bean id="cAdd" class="ch03_calc_01.CalAdd" />
    <bean id="cSub" class="ch03_calc_01.CalSub" />
    <bean id="cMul" class="ch03_calc_01.CalMul" />
    <bean id="cDiv" class="ch03_calc_01.CalDiv" />

    <bean id="myCalculator" class="ch03_calc_01.MyCalculator" />

    <bean id="calAssembler" class="ch03_calc_01.CalAssembler" >
        <constructor-arg ref="myCalculator"/>
        <constructor-arg ref="cAdd" />
        <constructor-arg ref="cSub" />
        <constructor-arg ref="cMul" />
        <constructor-arg ref="cDiv" />
    </bean>
</beans>
Code language: HTML, XML (xml)

beans를 추가한다.

이때 CalAssembler처럼 생성자에 매개변수가 있는 경우를 살펴보자.

<bean id="calAssembler" class="ch03_calc_01.CalAssembler" >
    <constructor-arg ref="myCalculator"/>
    <constructor-arg ref="cAdd" />
    <constructor-arg ref="cSub" />
    <constructor-arg ref="cMul" />
    <constructor-arg ref="cDiv" />
</bean>
Code language: HTML, XML (xml)

calAssebler bean과 CalAssember Class의 생성자를 비교해 보자.

public CalAssembler(MyCalculator calculator, CalAdd calAdd, CalSub calSub, CalMul calMul, CalDiv calDiv){...}
Code language: PHP (php)

CalAssember의 생성에 필요한 인자를 순서대로 calAssebler bean에 <constructor-arg>로 추가하면 된다.

물론 구체적으로 지정하는 방법도 있다.

constructor-arg 의 속성을 사용하면 된다. (아래에서 설명함. 다-2 참고)

이렇게 IoC 컨테이너에서 bean의 생성에 필요한 인자까지 자동으로 전달, 관리해 준다.

때문에 개발자는 applicationContext.xml에만 작성하면 다음부터는 편하게 사용할 수 있다.

생성자가 오버로딩 되어있다면 어떻게 되는 걸까?


1) 생성자만큼 bean 추가하기

만약에 CalAssembler에 첫 번째 인자로 MyCalculator를, 두 번째 인자로 CalAdd를 받는 생성자가 있다고 가정하자.

    public CalAssembler(MyCalculator calculator, CalAdd calAdd, CalSub calSub, CalMul calMul, CalDiv calDiv) {
        this.calculator = calculator;
        this.calAdd = calAdd;
        this.calSub = calSub;
        this.calMul = calMul;
        this.calDiv = calDiv;
    }

    public CalAssembler(MyCalculator calculator, CalAdd calAdd) {
        this.calculator = calculator;
        this.calAdd = calAdd;
    }
Code language: JavaScript (javascript)

이때 CalAssembler를 bean으로 추가하기 위해선 어떻게 해야 할까?

첫 번째 방법은 생성자 수만큼 applicationContext에 추가하는 것이다.

<!-- 첫 번째 생성자를 사용하는 CalAssembler bean 정의 -->
    <bean id="calAssemblerFull" class="ch03_calc_01.CalAssembler" >
        <constructor-arg ref="myCalculator"/>
        <constructor-arg ref="cAdd" />
        <constructor-arg ref="cSub" />
        <constructor-arg ref="cMul" />
        <constructor-arg ref="cDiv" />
    </bean>

    <!-- 두 번째 생성자를 사용하는 CalAssembler bean 정의 -->
    <bean id="calAssemblerPartial" class="ch03_calc_01.CalAssembler" >
        <constructor-arg ref="myCalculator"/>
        <constructor-arg ref="cAdd" />
    </bean>
Code language: HTML, XML (xml)

Spring는 기본적으로 bean을 Singleton으로 생성한다. (트래픽마다 계속 객체를 생성하게 되면 메모리 낭비가 심하기 때문**)**

Spring Container 내에서 한 번 생성된 bean 객체를 재사용하는 것을 의미한다.

다만 생성자만큼 bean을 따로 등록하게 되면 생성되는 bean의 객체는 그만큼 늘어난다.

출처 : https://velog.io/@gojaebeom/XML으로-Bean-등록하기


2) constructor-arg의 속성 이용하기

constructor-arg 태그는 bean의 생성자 인자를 정의할 때 사용된다.

public class Example {
    public Example(String a) {
        //...
    }

    public Example(String a, int b) {
        //...
    }

    public Example(int b, String c) {
        //...
    }
}
Code language: PHP (php)
<bean id="exampleBean1" class="path.to.Example">
    <constructor-arg index="0" value="SomeString"/>
    <constructor-arg index="1" value="5"/>
</bean>

<bean id="exampleBean2" class="path.to.Example">
    <constructor-arg index="0" value="5"/>
    <constructor-arg index="1" value="SomeString"/>
</bean>
Code language: HTML, XML (xml)

이러한 속성들을 조합하여 생성자 인자를 명확하게 지정하면 여러 개 오버로딩된 생성자도 처리가능하다.

참.고.로.

<!-- 에러 발생 -->
<bean id="exampleBean3" class="path.to.Example">
    <constructor-arg name="a" value="SomeString"/>
    <constructor-arg name="b" value="5"/>
    <constructor-arg name="c" value="SomeString"/>
</bean>
Code language: HTML, XML (xml)

위와 같은 방식으로 하나만으로 모든 생성자를 커버할 수 있지 않을까 생각해 봤다.

하지만 안된다고 한다.

Example 클래스에는 최대 두 개의 매개변수만을 받는 생성자들만 정의되어 있다.

name 속성을 활용해서도 세 개의 인자를 받는 생성자가 없기 때문에 Example 클래스의 적절한 생성자를 찾을 수 없으므로 오류를 발생시킨다.

그러니 상황에 따라 하나의 bean으로 모든 생성자를 커버 치지 못할 수 있다.


라. 나머지

더보기
package ch03_calc_01;

public class MyCalculator {
	public void calculate(int fNum, int sNum, ICalculator calculator) {
		int value = calculator.doOperation(fNum, sNum);
		System.out.println("result : " + value);
	}
}
Code language: PHP (php)
  package ch03_calc_01;

  public class CalAdd implements ICalculator {
      @Override
      public int doOperation(int fNum, int sNum) {
          // TODO Auto-generated method stub
          return fNum + sNum;
      }

  }
Code language: PHP (php)
  package ch03_calc_01;

  public class CalSub implements ICalculator {
      @Override
      public int doOperation(int fNum, int sNum) {
          // TODO Auto-generated method stub
          return fNum - sNum;
      }

  }
Code language: PHP (php)
  package ch03_calc_01;

  public class CalMul implements ICalculator {
      @Override
      public int doOperation(int fNum, int sNum) {
          // TODO Auto-generated method stub
          return fNum * sNum;
      }

  }
Code language: PHP (php)
  package ch03_calc_01;

  public class CalDiv implements ICalculator {
      @Override
      public int doOperation(int fNum, int sNum) {
          // TODO Auto-generated method stub
          return sNum !=0 ? (fNum + sNum) : 0;
      }

  }


Code language: PHP (php)

 

댓글 남기기