2023. 9. 22. 03:22ㆍ학부 강의/웹프로그래밍 (Spring)
0. 출처
아직 배우고 있는 중이라 부정확한 정보가 포함되어 있을 수 있습니다!
주의하세요!
올인원 스프링 프레임워크 참고.
1.디렉터리 구조
[project_name]/src/main/java
: .java 파일 관리.[project_name]/src/main/resource
s : 자원 관리. 스프링 설정 파일(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
한 번 설치한 모듈은 재사용된다.
다. 프로젝트 빌드 설정
<!-- 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>
<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();
}
}
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);
}
}
스프링 사용 이전과 비교해 보자.
//스프링 사용 이전
public CalAssembler(){
calculator = new MyCalculator();
calAdd = new CalAdd();
calSub = new CalSub();
calMul = new CalMul();
calDiv = new CalDiv();
assemble();
}
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>
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>
calAssebler bean과 CalAssember Class의 생성자를 비교해 보자.
public CalAssembler(MyCalculator calculator, CalAdd calAdd, CalSub calSub, CalMul calMul, CalDiv calDiv){...}
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;
}
이때 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>
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) {
//...
}
}
<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>
이러한 속성들을 조합하여 생성자 인자를 명확하게 지정하면 여러 개 오버로딩된 생성자도 처리가능하다.
참.고.로.
<!-- 에러 발생 -->
<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>
위와 같은 방식으로 하나만으로 모든 생성자를 커버할 수 있지 않을까 생각해 봤다.
하지만 안된다고 한다.
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);
}
}
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;
}
}
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;
}
}
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;
}
}
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;
}
}
'학부 강의 > 웹프로그래밍 (Spring)' 카테고리의 다른 글
[Spring] Spring Bean Scope (0) | 2023.10.07 |
---|---|
[Spring] 학사 정보 시스템 (0) | 2023.10.07 |
[Spring] Maven (0) | 2023.09.14 |
[Spring] DI, DIP, IoC (0) | 2023.09.09 |
[Spring] 개발 환경 구축 (0) | 2023.09.07 |