플레이데이터 - 28~29일차 Spring Framework 학습(1)

Kim Hyen Su·2023년 8월 9일

🌟Spring Framework

스프링 제공 기능

  • 👉객체 관리(IOC)
  • 👉MVC(DI) - 느슨한 결합력과 인터페이스
  • 트랜잭션 처리(AOP)
  • 인증과 권한(Servlet Filter)

🐽객체 관리

  • 스프링(스프링 컨테이너)의 핵심 기능은 객체를 생성 및 초기화하고 관리하는 것이다.
  • 스프링 프레임워크 사용자는 관리할 객체를 스프링 컨테이너에 빈 객체로 등록만 해주면 알아서 관리해준다.

IOC(Inversion Of Control)

  • 제어의 역전.
  • 개발자가 관리해야 할 객체들을 스프링에서 대신 관리해줌으로서 제어의 역전이 발생함.(스프링의 순기능)

🐽느슨한 결합력과 인터페이스

  • 애플리케이션 개발 중 소스 코드 수정 해야하는 경우가 많이 발생한다.

  • 하지만, 객체 간의 결합력이 높을수록 수정이 어려워지게 되며, 느슨할수록 수정 즉, 애플리케이션의 유지 보수가 쉬워진다.

  • 객체 간의 결합력을 느슨하게 하기 위해서는 인터페이스 를 사용하여 자료형을 선언하고, 이를 구현한 클래스 객체를 외부에서 생성 및 조립(대입)할 수 있도록 구현하여 결합력을 느슨하게 만들 수 있다.

🐽DI(Dependency Injection)

  • 스프링 프레임워크의 코어기능.
  • 일체형(Composition has a) : 생성자를 이용해 의존 객체를 내부에서 직접 생성하는 방식.
  • 조립형(Association has a) : setter를 이용해 외부에서 생성된 의존 객체를 조립하는 방식.
  • 느슨한 결합을 위해서는 조립형을 통해서 의존 객체를 조립하는 것이 용이하다.
  • 의존 객체를 Dependency이라고 하고, 이러한 객체를 조립하는 것을 Injection이라고 한다.
  • 스프링은 이처럼 Dependency Injection을 해주는 조립기이다.

🐽IoC 컨테이너(Inversion of Control)

  • 스프링은 개발자가 주문한 부품(객체)을 생성하고 조립해준다.
  • 개발자가 작성한 주문서는 일반적으로 xml 파일에 작성한다.
  • IoC 컨테이너의 역할
    • 주문서에 요청한 부품(의존 객체)을 담기위한 컨테이너.
    • 실질적으로 의존 객체를 생성하고 조립해주는 역할.
  • DI 순서 및 IoC의 의미.
    - 객체 관계 : A > B > C > D
    • 일체형 DI 순서 : A생성 → B생성 → C생성 → D생성
    • 조립형 DI 순서 : D생성 → C생성 → B생성 → A생성
    • 위처럼 객체 생성 및 조립의 순서가 역순으로 수행되기 때문에 IoC Container라고 한다.

🐽Dependency를 직접 Injection하기

public class Program {
	public static void main(String[] args) {
		Exam exam = new NewLecExam();
//		ExamConsole console = new InlineExamConsole(exam); // DI : ExamConsole interface를 구현한 다른 객체를 조립함에 따라 다른 기능을 구현한다. 이처럼 수동으로 코드를 수정하여 의존 주입을 해주는 것을 IoC 컨테이너에게 위임한다.
		ExamConsole console = new GridExamConsole(exam);
		console.print();
	}
}

🐽Spring DI를 위한 이클립스 플러그인 설치하기

  • 상단 네비게이션 바 [Help] → [Eclipse MarketPlace] → [spring 검색] → [Spring Tools 3 Add-On for Spring Tools install] →
    [File] → [New] → [Other] → [Spring] → [Spring Bean Configuration File]

🐽Spring xml 파일을 이용한 DI

1. Spring Bean Configuration File 생성

<?xml version="1.0" encoding="UTF-8"?>
<!-- 설정 파일 name 스페이스 -->
<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">
    
	<!-- 어떤 클래스(class)를 어떤 이름(id)의 빈으로 만들것인지 지정-->
	<!-- *반드시 class명을 명시할 때 패키지명까지 입력해줘야 함. -->
    <!-- *반드시 의존 주입 전에 빈객체로 등록해야 IoC 컨테이너에서 인식이 가능 -->
	<!-- Exam exam = new NewlecExam(); -->
	<bean id="exam" class="spring.di.entity.NewLecExam"/>
	
	<!-- ExamConsole console = new GridExamConsole(); -->
	<bean id="console" class="spring.di.ui.InlineExamConsole">
    
		<!-- console.setExam(exam); //DI-->
        <!-- 의존 주입 코드-->
		<!-- 실제 setExam()이라는 메서드를 호출할 때 set을 생략 후 첫자를 소문자로 바꿔준 뒤 메서드를 호출해준다.-->
		<!-- 따라서, name = (setE)exam 이며, 매개변수의 타입이 기본형이면 value, 참조형이면 ref를 사용한다. -->
		<property name="exam" ref="exam"></property>
	</bean>
</beans>

2. Spring을 이용한 DI

  • ApplicationContext 생성하기
    • Maven project로 변환
    • pom.xml 파일 내 <dependencies> ... </dependencies>에 spring context 라이브러리 의존 추가
    • xml 설정 파일을 IoC 컨테이너에 알려주기 위한 클래스
    • ClassPathXmlApplicationContext("xml 파일명");
ApplicationContext context = 
new ClassPathXmlApplicationContext("spring/di/order.xml");

// 이름(id) 값으로 가져오기 - 클래스 타입이 뭔지 모르기 때문에 casting 필수.
(class type)context.getBean("id 값");

// 클래스타입(class)로 가져오기
context.getBean(clazz.class); 
		

3. 값 형식 DI

  • 빈 객체의 필드값 초기화
  • 필드의 타입이 기본형인 경우, value 속성을 통해 값을 초기화 해준다.
    • 방법 1
      <property name="kor" value="20" />
    • 방법 2
		<property name="kor">
        	<value>10</value>
        </property>
  • 지시서에 bean으로 등록한 클래스의 private 필드에 값을 추가하기 위해서는 setter와 getter를 구현해줘야 접근이 가능하다.
- 오류 발생
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'exam' defined in class path resource 
[spring/di/order.xml]: Invalid property 'kor' of bean class
[spring.di.entity.NewLecExam]: Bean property 'kor' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?

public class NewLecExam
	private int kor;
    ...

<bean id="exam" class="spring.di.entity.NewLecExam">
	<property name="kor" value="10"/>
</bean>

- getter & setter 추가 시 정상 동작
public class NewLecExam
	private int kor;
    ...
    public int getKor(){
    	return this.kor;
    }
    public void setKor(int kor){
    	this.kor = kor;
    }
    

4. 생성자 DI

  • 지시서(.xml)에서 <constructor-arg/> 태그를 사용하여 오버로딩된 생성자의 매개변수 값을 추가해줄 수 있다.
	<bean id="exam" class="spring.di.entity.NewLecExam">
    	<constructore-arg> 
        <name>"매개변수명"</name>
        <index>"0부터 시작, 매개변수 순서 인덱스"</index>
        <type>"동일한 매개변수 갯수의 타입만 다른 생성자가 2개 이상 오버로딩된 경우, 사용할 생성자의 매개변수 타입 명시." </type>
        <value>"매개값"</value>
        </constructor-arg>
    </bean>
  • 조금 더 간결한 태그로 속성을 설정하는 방법
namespaces에 아래 코드 추가.
<beans ....
	xmlns:p="http://www.springframework.org/schema/p" //추가
>

namespace 추가 후, 아래처럼 간결한 형태로 설정 가능.
<bean id="exam" class="spring.di.entity.NewLecExam" p:kor="10" p:eng="20" p:math="30" p:com="40">

namespace란?

  • 특정 처리기에 의해 처리할 태그를 특정할 때 사용.
  • 태그를 구분하기 위해 사용.

5.컬렉션타입 의존 객체 생성과 DI

  • <bean id="" class="java.util.ArrayList"></bean>
  • ArrayList 클래스 생성자 이용
	<bean id="exams" class="java.util.ArrayList">
    	<constructor-arg>
        	<list>
            	<bean class="spring.di.entity.NewLecExam" p:kor="10" p:eng="10"/>
                <ref bean="exam"/>
            </list>
        </constructor-arg>
    </bean>
  • 조금 더 간결한 태그로 속성을 설정하는 방법
namespaces에 아래 코드 추가.
xmlns:util="http://www.springframework.org/schema/util"

<util:list id="exams" list-class="java.util.ArrayList">
		<bean class="spring.di.entity.NewLecExam" p:kor="10" p:eng="10"></bean>
		<ref bean="exam"/>
</util:list>
profile
백엔드 서버 엔지니어

0개의 댓글