본문 바로가기
Java/Spring

Spring) xml을 통한 context 작성 - IoC 지원 특징 파악하기 (bean 생성)

by 박채니 2022. 8. 12.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


Maven Project 생성

 

spring context 의존 주입받기

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.ce</groupId>
  <artifactId>hello-springbean2</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>hello-springbean2</name>
  
  <dependencies>
  	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-context</artifactId>
	    <version>5.2.22.RELEASE</version>
	</dependency>
  </dependencies>
  
</project>

 

Context

- spring에서 bean을 관리하는 객체

- 하나의 어플리케이션에 하나 이상의 context가 존재할 수 있음

context가 여러개인 경우

 


 

 

IoC 지원 특징 파악하기

 

Tv interface

public interface Tv {
	void powerOn();
}

 

LgTv

public class LgTv implements Tv {
	
	public LgTv() {
		System.out.println("LgTv 객체 생성!");
	}
	
	public void powerOn() {
		System.out.println("LgTv Power On!");
	}

}

 

SamsungTv

public class SamsungTv implements Tv {
	
	public SamsungTv() {
		System.out.println("SamsungTv 객체 생성!");
	}
	
	public void powerOn() {
		System.out.println("SamsungTv Power On!");
	}

}

 

TvMain

public class TvMain {

	public static void main(String[] args) {
		
	}

}

 

Spring Bean Configuration File 생성

(build-path에서 관리되어야 하므로, src/main/resources 하위에 생성)

 

beans 루트태그 하위에 spring이 관리해줬으면 하는 타입들을 명시해주면 됩니다.

<?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="lgTv" class="com.ce.spring.tv.LgTv"></bean>
	<bean id="samsungTv" class="com.ce.spring.tv.SamsungTv"></bean>
</beans>

 

어플리케이션과 설정 문서 연결 시키기

public class TvMain {

	public static void main(String[] args) {
		String configLocation = "classpath:tv-context.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
		System.out.println("=================== spring container 초기화 완료 ===================");
	}

}

@콘솔출력값
LgTv 객체 생성!
SamsungTv 객체 생성!
=================== spring container 초기화 완료 ===================

초기화 단계에 bean이 생성되어 해당 클래스의 객체가 만들어진 것을 확인할 수 있습니다.

spring이 대신 기본 생성자를 호출하여 가지고 있던 것이죠.

 

특정 객체가 필요하다면, getBean()을 통해 bean을 가져올 수 있습니다.

getBean("id값")

getBean(클래스객체)

String configLocation = "classpath:tv-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");

Tv lgTv = (Tv) context.getBean("lgTv");	// id값으로 가져오기 (Object 반환하므로 다운캐스팅 필요)
lgTv.powerOn();

Tv lgTv2 = context.getBean(LgTv.class);	// class객체로 가져오기
lgTv2.powerOn();

System.out.println(lgTv);
System.out.println(lgTv2);
System.out.println(lgTv == lgTv2);

@콘솔출력값
LgTv 객체 생성!
SamsungTv 객체 생성!
=================== spring container 초기화 완료 ===================
LgTv Power On!
LgTv Power On!
com.ce.spring.tv.LgTv@604ed9f0
com.ce.spring.tv.LgTv@604ed9f0
true

 id값으로 가져올 때Object를 반환하기 때문에 다운캐스팅이 필요하며, 클래스 객체로 가져올 때해당 클래스타입으로 반환하기 때문에 다운캐스팅이 필요하지 않습니다.

또한, spring은 기본적으로 bean을 singleton 패턴으로 관리하기 때문에 하나의 객체를 생성하여 재사용합니다.

따라서 lgTv, lgTv2의 해쉬코드가 동일하여 동등비교 시 true가 출력된 것을 확인할 수 있습니다.

 

bean 설정

scope

- singleton (기본값)

- prototype : getBean 요청 시마다 객체 생성

- request : request마다 객체 생성

- session : session마다 객체 생성

<!-- 
    scope
        - singleton (기본값)
        - prototype : getBean 요청 시마다 객체 생성
        - request : request마다 객체 생성
        - session : session마다 객체 생성
 -->
<bean id="lgTv" class="com.ce.spring.tv.LgTv" scope="prototype"></bean>
<bean id="samsungTv" class="com.ce.spring.tv.SamsungTv"></bean>

 

String configLocation = "classpath:tv-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");

Tv lgTv = (Tv) context.getBean("lgTv");	// id값으로 가져오기 (Object 반환하므로 다운캐스팅 필요)
lgTv.powerOn();

Tv lgTv2 = context.getBean(LgTv.class);	// class객체로 가져오기
lgTv2.powerOn();

System.out.println(lgTv);
System.out.println(lgTv2);
System.out.println(lgTv == lgTv2);

@콘솔출력값
SamsungTv 객체 생성!
=================== spring container 초기화 완료 ===================
LgTv 객체 생성!
LgTv Power On!
LgTv 객체 생성!
LgTv Power On!
com.ce.spring.tv.LgTv@604ed9f0
com.ce.spring.tv.LgTv@6a4f787b
false

lgTv의 scope를 "prototype" 즉, getBean 요청 시마다 객체를 생성하도록 설정하였습니다.

그 결과, spring container 초기화 단계에서 객체가 생성되지 않고, getBean()으로 요청할 때마다 객체가 생성되는 것을 확인할 수 있습니다.

따라서 두 객체의 해쉬코드가 상이하고, 동등비교 시 false가 출력됩니다.

 

lazy-init

- default : spring의 기본 동작에 맞게 bean 생성 (기본 동작은 false)

- true : 나중에 bean을 생성

<bean id="samsungTv" class="com.ce.spring.tv.SamsungTv" lazy-init="true"></bean>

 

String configLocation = "classpath:tv-context.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configLocation);
System.out.println("=================== spring container 초기화 완료 ===================");

Tv lgTv = (Tv) context.getBean("lgTv");	// id값으로 가져오기 (Object 반환하므로 다운캐스팅 필요)
lgTv.powerOn();

Tv lgTv2 = context.getBean(LgTv.class);	// class객체로 가져오기
lgTv2.powerOn();

System.out.println(lgTv);
System.out.println(lgTv2);
System.out.println(lgTv == lgTv2);

SamsungTv samsungTv = context.getBean(SamsungTv.class);
System.out.println(samsungTv);

@콘솔출력값
=================== spring container 초기화 완료 ===================
LgTv 객체 생성!
LgTv Power On!
LgTv 객체 생성!
LgTv Power On!
com.ce.spring.tv.LgTv@66a3ffec
com.ce.spring.tv.LgTv@77caeb3e
false
SamsungTv 객체 생성!
com.ce.spring.tv.SamsungTv@604ed9f0

SamsungTv를 lazy-init="true"로 설정하였더니, 이번에도 spring container 초기화 시에는 객체가 생성되지 않았고

getBean()요청 시 객체가 생성되는 것을 확인할 수 있습니다.