에러 탈출 일지

IoC 컨테이너 본문

개발/SpringFramework

IoC 컨테이너

뉴NEW 2022. 11. 11. 09:47

< IoC 컨테이너 >

예제: 프로젝트 _04_SpringFramework_SpringContainer

 

1. factory 디자인 패턴: 필용한 모듈(객체 등)을 미리 factory 안에 모두 생성한 뒤 알맞은 모듈을 꺼내 사용하는 방식

2. 스프링 컨테이너에는 factory 디자인 패턴이 적용되어 있다.

  - <bean>으로 등록된 객체들을 스프링 컨테이너가 구동될 때 생성한다.

 - @Component(@Controller, @Service, @Repository 등)을 가지는 객체들도 스프링 컨테이너가 구동될 때 생성한다

 - 이렇게 생성된 객체들을 factory안에 가지고 있다가 알맞은 객체 호출이 있을 때 알아서 의존성 주입을 실행한다

3. IoC (Inverse of Control: 제어의 역전)

  - 기존에 개발자들이 하던 객체 생성 및 의존성 주입을 스프링 컨테이너에서 알아서 처리한다.

 

 

public class TvUser {

	public static void main(String[] args) {
		// TV인터페이스를 이용하여 결합도와 의존성을 낮춤

		TV tv;
        
		tv = new SamsungTV();
		tv.turnOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.turnOff();
		
		tv = new LgTV();
		tv.turnOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.turnOff();
		
	}

}

- 티비를 변경하고 싶을 때 인스턴스화 하는 부분의 소스코드를 지속적으로 변경해야 한다.
- 스프링에선 설정파일(스프링 컨테이너)에 미리 객체를 생성한 뒤 DI(의존성 주입)해주는 것을 지원한다. → 팩토리 패턴

 

 

bean id 객체 생성

<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
	<!-- Root Context(프로젝트 별로 파일 이름이 다를 수 있음): 부모 스프링 컨테이너를 만드는 설정 파일 -->	
	
	<!-- bean 객체 생성 -->
	<!-- 컨테이너가 구동되면서 자동으로 생성 -->
	<!-- 어떤 id로 어떤 객체를 생성할건지 -->
	<bean id="sTv" class="com.ezen.spring.polymorphism.SamsungTV"/>
	<bean id="lTv" class="com.ezen.spring.polymorphism.LgTV"/>
</beans>

 

 

public class TvUser {

	public static void main(String[] args) {
		// 1. 스프링 컨테이너 구동      
		AbstractApplicationContext factory = 
				new GenericXmlApplicationContext("root-context.xml");
		
		// 2. DL과 DI
		// DL(Dependency Lookup): sTv라는 id를 가진 bean객체를 찾음
		// DI(Dependency Injection): DL에서 찾은 bean객체를 tv 의존성에 주입
		
        TV tv = (TV)factory.getBean("sTv");
		tv.turnOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.turnOff();
		
		// 3. 스프링 컨테이너 종료
		factory.close();
		
	}

}

     TV tv = (TV)factory.getBean("sTv"); 에서  아이디만 바꿔주면 됨 (코드가 더욱 간단해짐)

 

 

 

< 스프링 XML 파일 설정 >

1. \<beans\> 루트 엘리먼트

- 원격 저장소에 있는 설정 파일을 참조하여  \<beans\>의 생명주기 관리

\<beans\>외의 다른 엘리먼트 사용가능 하도록 만듦. 또한 다른 여러가지 서비스를 제공

- 스프링 설정 파일은 항상 루트 엘리먼트로  \<beans\>를 사용해야 한다.

- namespce 탭을 이용하면 사용할 엘리먼트의 설정 파일 참조가 쉬워진다.

 

2. \<import\> 엘리먼트

- 스프링 설정 파일에서 사용할 외부 파일을 참조할 때 사용

- 문제발생: 모든 설정들이 하나의 스프링 설정 파일에 작성되면 스프링 설정 파일의 길이기 길어지고 수정도 쉽지 않음.

  대표적으로 DataBase 설정이나 Transaction 설정 등을 외부 파일로 분리하여 참조한다. (참조 파일 resource 속성으로 지정)

 

3. \<bean>\ 엘리먼트

- 스프링 설정 파일에 클래스 등록하고, 그 클래스에 대한 객체가 자동적으로 생성되야 할 때 \<bean\>엘리먼트 사용.

- \<bean\> 엘리먼트로 등록된 클래스는 스프링 컨테이너 구동시 자동으로 객체 생성

 

4. \<bean\> 엘리먼트의 속성

(1) init-method

- init-method 속성을 사용하면 객체가 생성될 때 호출할 메소드를 지정할 수 있다.

- \<bean\> 엘리먼트로 생성되는 객체는 항상 기본 생성자를 호출하기 때문에 멤버변수의 초기화가 필요한 객체에는 init-method 속성을 초기화 메소드를 등록해야 한다

- \<bean id="sTv" class="....SamsungTV" init-method="메소드명"\>

- 예제 프로젝트: _005_SpringFramework_BeanProperties

 

(2) destory-method

- 스프링 컨테이너가 객체를 삭제하기 전에 객체에서 처리할 동작을 메소드로 만들어서 지정한다.

- \<bean id="sTv" class="....SamsungTV" destroy-method="메소드명"\>

- 예제 프로젝트: _005_SpringFramework_BeanProperties

 

(3) lazy-init

- 객체 생성 시점을 지정. true나 false로 지정 가능하며 기본값 false로  설정되어 스프링 구동될 때 객체를 생성.

- true로 설정했을 경우 사용자가 그 객체를 요청했을 때  객체를 생성

- \<bean id="sTv" class="....SamsungTV" lay=zy-init="true or false"\>

- 예제 프로젝트: _005_SpringFramework_BeanProperties

 

(4) scope

- 객체 생성 방식을 지정. singleton을 지정할 수 있는데 singleton으로 지정하면 하나의 객체만 생성하고, 이 객체를 공유해서 사용

- 지정하지 않을시 새로운 객체를 계속해서 생성

- 스프링은 기본값이 singleton으로 하나의 객체만 생성

- prototype 지정시 여러 개 객체 생성

- scope="prototype"일 때 생성되는 객체들은 singletonBean이 아닌 disposableBean으로 생성되기 때문에 삭제할 수가 없다.

- disposableBean의 특성은 다른 지원에 대한 참조를 가질 수 없고 DB연결이나 Session객체 같이 참조 후에 바로 가비지 컬렉터에 의해 삭제됨.

- disposableBean을 스프링에서 삭제시키려면 singletonBean 전처리기를 생성하여 처리해야 한다.
- 출처: https://bluebreeze0812.github.io/learn/2019/10/17/Spring-Destroy-Prototype-Beans/

- \<bean id="sTv" class="...SamsumgTV" scope="singleton or prototype">

- 예제 프로젝트: _005_SpringFramework_BeanProperties

 

 

< 의존성 주입 >

1. IoC의 두 가지 방식

- DL(Dependency Lookup)과 DI(Dependency Injection)은 스프링에서 제공하는 IoC의 두 가지 방식이다.

- DL은 알맞은 의존성을 검색하는 기능

- DI은 의존성을 주입하는 기능

- DL과 DI가 항상 함께 실행되지는 않는다. (DI가 좀 더 많은 방법 가지고 있음)

- DI 방식의 종류: setter injection(세터함수를 이용한 의존성 주입), contructor injection(생성자함수를 이용한 의존성 주입) 

- 예제 프로젝트: _006_SpringFramework_DI

 

2. 생성자 함수를 이용한 DI
- 생성자 함수를 통한 의존성 주입은 스프링 설정 파일에 constructor-arg 엘리먼트를 이용해서 멤버객체에 들어갈 객체를 참조하여 기본 생성자가 아닌 다른 생성자를 호출하므로써 이뤄진다.

-예제 프로젝트: _007_SpringFramework_DI_Constructor

 

- 다중 매개변수인 생성자 함수일 경우 constructor-arg 엘리먼트를 여러 개 사용하여 매핑한다. 객체는 ref속성으로 참조 일반적인 값이 들어갈 경우 value속성으로 설정.

- public SamsungTV(SonySpeaker speaker, int price) {

 

}

<bean> <constructor-arg ref="sony"></constructor-arg> <constructor-arg value="100000"></constructor-arg> </bean>

- 여러개의 매개변수가 존재하는 생성자 함수 호출할 때는 constructor-arg 엘리먼트의 index속성으로 몇 번째 매개변수인지 명시할 수 있다.

 <bean> 

<constructor-arg index="0" ref="sony"></constructor-arg>

 <constructor-arg index="1" value="100000"></constructor-arg> 

</bean>

- 예제 프로젝트: _007_SpringFramework_DI_Constructor
- 예제 프로젝트: _008_SpringFramework_DI_Constructor_Interface

 

3.세터 함수를 이용한 DI
- 의존성을 주입할 객체에 해당 멤버변수(속성)에 해당하는 세터함수를 미리 작성한다.
- <property> 엘리먼트를 사용하여 해당 세터함수를 호출 <bean> <property name="세터함수의 이름" ref or value="멤버변수에 의존성 주입할 값이나 객체"></property> </bean>
- setSpeaker()라는 세터함수가 존재할 때 세터함수의 이름은 set을 제외한 Speaker가 세터함수의 이름이 되고 첫 번째 단어의 첫 글자는 소문자로 지정돼야 하기때문에 speaker가 최종적인 세터함수의 이름이 됩니다.(카멜케이스 적용) setNameList() -> nameList

- 예제 프로젝트: _009_SpringFramework_DI_Setter

 

- p namespace를 사용하여 세터함수를 효율적으로 호출하기 <bean p:멤버변수명(멤버변수가 객체일 경우)-ref="의존성 주입될 객체" p:멤버변수명(멤버변수가 일반 데이터타입)="넣어줄 값" > </bean>

- 예제 프로젝트: _009_SpringFramework_DI_Setter

 

4. 어노테이션을 이용한 의존성 주입

- context namespace를 추가하영 사용한다.

- context namespace에는 component-scan이라는 기능이 있다. 속성 값으로 패키지를 지정해서 지정된 패키지에 있는 클래스들 안에서 @Component가 선언된 클래스들만 찾아서 자동으로 객체로 만듦.
- @Component는 최상위 어노테이션이다. @Controller, @Service, @Repository 등은 @Component를 상속받아 구현됨. 따라서 component-scan 위 나열한 어노테이션들도 함께 걸린다.
- 스프링 설정 파일 <context:component-scan base-package="컴포넌트 스캔할 패키지명">
- 클래스 선언부 위줄에 어노테이션을 달아준다. @Component public class SamsungTV
- component-scan으로 생성될 객체에 id를 지정하는 방식은 @Component("id값")

- 예제 프로젝트: _010_SpringFramework_DI_Annotation

'개발 > SpringFramework' 카테고리의 다른 글

JSTL(Jsp Standard Tag Library)  (0) 2022.11.17
트랜잭션  (0) 2022.11.16
AOP  (0) 2022.11.15
비즈니스 컴포넌트(Service, ServiceImpl, DAO)  (0) 2022.11.14
Spring Framework  (0) 2022.11.11