코딩하는 문과생

[Spring] Spring 프레임워크(1) - 개요, Maven, IoC 본문

웹 프로그래밍/Spring

[Spring] Spring 프레임워크(1) - 개요, Maven, IoC

코딩하는 문과생 2020. 3. 8. 12:31

[개요]

- 스프링에 사용되는 모듈들

  • Data Access/Integration 영역: JDBC, ORM...

  • Web 영역: Web Socket, Servlet, Web, Portlet...

  • Core Container(Spring Container): Beans, Core, Context, SpEL

  • Test 영역

  • AOP

  • Aspects

  • ...

- 개발 환경 종류

  • Eclipse + Plugin

  • STS

  • IntelliJ

- 설치 순서

  1. 자바 SDK 설치 확인

  2. STS설치

  3. Tomcat설치


[Maven]

- Spring의 시작

스프링을 사용하기 위해 '메이븐 빌드'가 필요하다.

 

- Maven이란?

  • 자바 개발의 사실상 표준 빌드 툴

  • XML 설정 파일을 사용

  • Gradle도 가능

- CoC:Convention over Configuration

설정보다는 관례를 따르겠다.

cf. 웹프레임워크 Express: Configuration over Convention

 

[특징]

- Java 기반 Web App의 Best Practice를 따른다.(개발 디렉토리 구조와 빌드단계가 비슷하다.)

 

- 의존성 관리를 자동으로 수행

Maven 중앙 저장소(Central Repository)를 제공하여 자바 라이브러리에 대한 생태계 조성

cf. nodejs의 npm과 비슷

 

- pom.xml: 메이블의 메인 설정 파일

메이븐 프로젝트를 의미, 프로젝트 루트에 위치

IDE에서 불러오기가 쉽다.

 

- 메이븐 프로젝트 설정 시 필수사항

  • 프로젝트 명(빌드 결과물): artifactID를 사용

  • 그룹 아이디: kr.co.company

  • 버전: SNAPSHOT 버전 사용 - 개발 버전, RELEASE 버전 - 배포 버전


[IoC: 제어의 역행]

객체에 대한 제어권(객체의 생성, 생명주기 관리)을 스프링 컨테이너가 관리한다.

  • DL: Dependency Lookup(의존성 검색) - Bean들을 looup
  • DI: Dependency Injection(의존성 주입) - Bean 설정을 통해 컨테이너가 자동으로 연결

[DI 종류]

  • Setter Injection

  • Constructor Injection

  • Method Injection

  • Managed Bean: 스프링 컨테이너에 의해서 관리되는 객체

  • Spring Container: 관리되어지는 빈이 모여 있는 곳, Application Context 클래스로 구현된다.

 

[POJO란?]

단순히 getter/setter만 가진 객체

 

 

ex. DL

- HelloDAO.java

package kr.co.acomp.hello;

public class HelloDAO {
	public int addTwoNumber(int a, int b) {
		return a + b;
	}
}

- spring-context.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="helloDAO" class="kr.co.acomp.hello.HelloDAO" />
</beans>

- HelloMain.java

package kr.co.acomp.hello;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloMain {

	public static void main(String[] args) {
		//빈 스프링 컨테이너 생성, 빈 또한 생성
		AbstractApplicationContext ctx = 
				new ClassPathXmlApplicationContext("/spring-context.xml");

		//getBean(): DL 지원, 생성되어 있는 빈 중 해당 빈을 찾는다.
		HelloDAO dao = ctx.getBean("helloDAO", HelloDAO.class);
		int result = dao.addTwoNumber(3, 5);
		System.out.println(result);

	}

}

[DI]

DI: 각 클래스간 의존 관계를 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것을 말한다.

  • 빈 설정 파일에서 의존관계 정보를 추가만 하면 된다.

  • 실행시에 동적으로 의존관계가 생성된다.

  • 컨테이너가 흐름의 주체가 되어 애플리케이션 코드에 의존관계를 주입해준다.

 

장점: 코드가 단순해지고 컴포넌트 간의 결합도가 제거된다.

 

  • Setter Injection: setter 메서드를 이용

  • Constructor Injection: 생성자를 이용

  • Method Injection: 일반 메서드 사용

 

- Spring 컨테이너 = Spring DI 컨테이너 = Bean Factory = Application Context

: Bean Factory: 빈을 등록, 생성, 반환 관리, 보통 빈 팩토리를 바로 사용하지 않고 이를 확장한 Application context를 사용한다.

 

 

ex. setter DI

-HelloService.java (HelloDAO는 그대로 사용)

package kr.co.acomp.hello.service;

import kr.co.acomp.hello.HelloDAO;

public class HelloService {
	
	private HelloDAO helloDAO;
	
	public void setHelloDAO(HelloDAO dao) {
		this.helloDAO = dao;
	}
	
	public int calcTwoNumbers(int a, int b) {
		
		return helloDAO.addTwoNumber(a, b);
	}
}

 

-spring-context.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="helloDAO" class="kr.co.acomp.hello.HelloDAO" />
	<bean id="helloService" class="kr.co.acomp.hello.service.HelloService">
		<!-- DI: name: setter이름 등록, ref: 실제 주입할 객체 -->
		<property name="helloDAO" ref="helloDAO"/>
	</bean>
</beans>

 

- HelloMain.java

package kr.co.acomp.hello;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import kr.co.acomp.hello.service.HelloService;

public class HelloMain {

	public static void main(String[] args) {
		//빈 스프링 컨테이너 생성, 빈 또한 생성
		AbstractApplicationContext ctx = 
				new ClassPathXmlApplicationContext("/spring-context.xml");

		//getBean(): DL 지원, 생성되어 있는 빈 중 해당 빈을 찾는다.
		HelloService service = ctx.getBean("helloService", HelloService.class);
		int result = service.calcTwoNumbers(4, 5);
		System.out.println(result);

	}

}

 

 

ex. Constructor DI

 

-HelloService.java 수정

package kr.co.acomp.hello.service;

import kr.co.acomp.hello.HelloDAO;

public class HelloService {
	
	private HelloDAO helloDAO;
	
	public HelloService(HelloDAO helloDAO) {
		this.helloDAO = helloDAO;
	}



	public int calcTwoNumbers(int a, int b) {
		
		return helloDAO.addTwoNumber(a, b);
	}
}

-spring-context.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="helloDAO" class="kr.co.acomp.hello.HelloDAO" />
	<bean id="helloService" class="kr.co.acomp.hello.service.HelloService">
		<!-- setter DI: setter이름 등록, ref: 실제 주입할 객체 -->
		<!-- <property name="helloDAO" ref="helloDAO"/> -->
		<!-- constructor DI -->
		<constructor-arg ref="helloDAO"/>
	</bean>
</beans>

 

 

ex. 2개의 Injection 사용

-AnotherDAO 추가

package kr.co.acomp.hello.dao;

public class AnotherDAO {

	public int square(int a) {
		return a * a;
	}
}

-HelloService수정(setter DI이용)

package kr.co.acomp.hello.service;

import kr.co.acomp.hello.dao.AnotherDAO;
import kr.co.acomp.hello.dao.HelloDAO;

public class HelloService {
	
	private HelloDAO helloDAO;
	private AnotherDAO anotherDAO;
	
	public void setHelloDAO(HelloDAO dao) {
		this.helloDAO = dao;
	}

	public void setAnotherDAO(AnotherDAO dao) {
		this.anotherDAO = dao;
	}

	public int calcTwoNumbersAndSquare(int a, int b) {
		
		int result = helloDAO.addTwoNumber(a, b);
		return anotherDAO.square(result);
	}
}

-spring-context.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="helloDAO" class="kr.co.acomp.hello.dao.HelloDAO" />
	<bean id="anotherDAO" class="kr.co.acomp.hello.dao.AnotherDAO" />
	<bean id="helloService" class="kr.co.acomp.hello.service.HelloService">
		<property name="helloDAO" ref="helloDAO"/>
		<property name="anotherDAO" ref="anotherDAO"/>
	</bean>
</beans>

-Main 실행

package kr.co.acomp.hello;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import kr.co.acomp.hello.service.HelloService;

public class HelloMain {

	public static void main(String[] args) {
		AbstractApplicationContext ctx = 
				new ClassPathXmlApplicationContext("/spring-context.xml");

		HelloService service = ctx.getBean("helloService", HelloService.class);
		int result = service.calcTwoNumbersAndSquare(4, 3);
		System.out.println(result);
        //49
	}
}