framework/spring IOC(제어의 역행)

[springIOC] 6. DI | 자동주입 | 자동으로 Inject 하는 법

jeri 2024. 7. 28. 23:42
반응형

01. 💖Spring Bean Configuration File

[05-3.autowire.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>">
    
    
    
    
	<!-- StudentDAO 인터페이스를 상속받은 자식클래스를 Spring Bean으로 등록 -->
	<bean class="xyz.itwill05.di.StudentJdbcDAO" id="studentJdbcDAO"/>  <!-- byName 속성값을 사용할 경우 의존성 주입이 안됨 -->
	<!-- <bean class="xyz.itwill05.di.StudentJdbcDAO" id="studentDAO"/> --> <!-- byName 속성값을 사용할 경우 의존성 주입됨 -->
	<bean class="xyz.itwill05.di.StudentMybatisDAO" id="studentMybatisDAO"/> <!-- byType 속성값을 사용할 경우 의존성 주입이 실패됨 -->

1) 수동 의존성 주입

	<!-- StudentService 인터페이스를 상속받은 자식클래스를 Spring Bean으로 등록 -->
	<!-- => StudentServiceImpl 클래스의 studentDAO 필드에 studentDAO 인터페이스를 상속받은
	자식클래스의 객체(Spring Bean)가 저장되도록 의존성 주입 - 의존관계 성립 -->
	<!-- => 의존성 주입을 하지 않으면 StudentServiceImpl 클래스의 메소드에서 StudentDAO
	인터페이스를 상속받은 자식클래스의 메소드를 호출할 경우 NullPointerException 발생 -->
	<!-- property 엘리먼트를 사용하여 studentDAO 필드에 StudentDAO 인터페이스를 상속받은 자식
	클래스의 객체(Spring Bean)가 저장되도록 설정 - Setter Injection -->
	<!-- => 개발자 직접 만든 의존성 주입 - 개발자가 아래의 명령 작성을 통해 Spring Container에게 명령을 내림 -->
	<!-- 해석)StudentServiceImpl 클래스를 studentService라고 부를게(식별자)-->
	<!-- 해석)StudentServiceImpl 클래스 안에 studentDAO명의 필드가 있는데, 그 필드에는 studentJdbcDAO 객체 저장할거야!!! -->
	<!--
	<bean class="xyz.itwill05.di.StudentServiceImpl" id="studentService">
		<property name="studentDAO" ref="studentJdbcDAO"/>
	</bean>
	 -->

2) 자동 의존성 주입

autowire = "no"

	 <!-- autowire 속성 : no(기본), byName, byType, constructor 중 하나를 속성값으로 설정 -->
	 <!-- => 스프링 컨테이너가 Spring Bean의 의존관계를 자동으로 구현되도록 설정하는 속성 -->
	 <!-- no 속성값 : 자동으로 의존관계를 구현하는 기능 미사용 -->
	 <!--
	 <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentService" autowire="no">
		 <property name="studentDAO" ref="studentJdbcDAO"/>
	 </bean>
	  -->

autowire = "byName"

	 <!-- Setter Injection -->

	 <!-- byName 속성값 : Spring Bean으로 등록된 클래스의 필드명과 같은 이름의 식별자(beanName)로
	 선언된 Spring Bean을 제공 받아 필드에 저장되도록 의존성 주입 - Setter Injection 이용 -->
	 <!-- => 필드명과 같은 이름의 식별자(beanName)로 선언된 Spring Bean이 없는 경우 의존성 [미주입] - NullPointerException 발생 -->
	 <!-- <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentService" autowire="byName"/> -->

필드명과 같은 이름의 식별자(beanName)로 미선언
필드명과 같은 이름의 식별자(beanName)로 선언

autowire = "byType"

	 <!-- byType 속성값 : Spring Bean으로 등록된 클래스의 필드와 같은 자료형의 Spring Bean을
	 제공 받아 필드에 저장되도록 의존성 주입 - Setter Injection 이용 -->
	 <!-- => 필드의 자료형이 인터페이스인 경우 인터페이스를 상속받은 자식클래스로 등록된
	 Spring Bean의 객체를 제공받아 필드에 저장되도록 의존성 주입 -->
	 <!-- => 필드와 같은 자료형의 Spring Bean이 2개 이상 등록된 경우 의존성 [주입 실패] - NoUniqueBeanDefinitionException 발생 - 주입실패 -->
	 <!-- <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentService" autowire="byType"/>  -->

autowire = "constructor"

	 <!-- Constructor Injection -->
	 <!-- => 전제조건) 반드시 매개변수가 있는 생성자가 있어야함-->
	 <!-- constructor 속성값 : Spring Bean으로 등록된 클래스의 필드와 같은 자료형의 Spring Bean을
	 제공 받아 필드에 저장되도록 의존성 주입 - Constructor Injection 이용 -->
	 <!-- => 필드의 자료형이 인터페이스인 경우 인터페이스를 상속받은 자식클래스로 등록된
	 Spring Bean의 객체를 제공받아 필드에 저장되도록 의존성 주입 -->
	 <!-- => 필드와 같은 자료형의 Spring Bean이 2개 이상 등록된 경우 기본 생성자로 객체 생성 - 의존성 [미주입] - NullPointerException 발생 : 그냥 기본생성자로 만듦 -->
	 <bean class="xyz.itwill05.di.StudentServiceImpl" id="studentService" autowire="constructor"/>

	 <!-- =>Spring Bean Configuration File로 의존성주입을 할 경우 :
	 		일반적으로 필드의 자료형이 인터페이스인 경우 상속받은 자식 클래스들이 많으므로
	 		자동완성 injection을 속성값을 이용할 경우 에러 많이 발생함 -->
	 <!-- => 자동injection 보다는 수동injection을 권장 -->

	 <!-- =>어노테이션으로 의존성주입을 할 경우 :
	 		무조건 자동완성 injection만 이용함, 수동완성 injection이 없고,
	 		injection시 값주입도 따로 없고 모두 객체주입을 이용함 -->
</beans>

 

 

 

02. 요청처리

AutoWireApp.java
package xyz.itwill05.di;

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

public class AutoWireApp {
	public static void main(String[] args) {
		System.out.println("============= Spring Container 초기화 전 =============");
		ApplicationContext context = new ClassPathXmlApplicationContext("05-3_autowire.xml");
		System.out.println("============= Spring Container 초기화 후 =============");
		StudentService service = context.getBean("studentService",StudentService.class);
		service.addStudent(null);
		System.out.println("======================================================");
		((ClassPathXmlApplicationContext)context).close();
	}
}
반응형