학원/spring

12.27 (DI, 컨테이너 생성-프로퍼티 방식, 인자 2개)

쿠룽지 2023. 12. 27. 21:59
728x90
반응형

 

 

 

<DI 학습>

1. 생성자 방식

2. 프로퍼티 방식

종류는 두 가지가 있고, 웹으로 넘어가면 생성자 방식은 거의 쓰지 않음 (실제 웹사이트 생성 시 거의 프로퍼티 방식)

기본문법을 배우기 위해 생성자 방식부터 예제 작성해볼 것임

 

(생성자 방식 기본인자, 생성자 방식 인자2개, 프로퍼티 방식 기본인자, 프로퍼티 방식 인자2개 순)

 

 

 

 

 

public class Student {
	private Car car;
    
    public Student(Car car){
    	this.car = car;
    }
}
public class Car{}

 

1) Car 생성

2) Student 생성

 

car는 독립적이지만 student를 사용하기 위해선 car객체가 먼저 생성되어야 함

이처럼 의존관계인 컨테이너를 생성하고 di를 학습할거임

 

 


 

 

의존적이지 않은 클래스

kr.spring.ch04

WriteArticleDAO

package kr.spring.ch04;

public class WriteArticleDAO {
	public void insert(){
    	System.out.println("WriteArticleDAO의 insert() 메서드 실행");
    }
}

 

 

 

 

WriteArticleDAO에 의존하는 클래스

kr.spring.ch04

WriteArticleService

package kr.spring.ch04;

public class WriteArticleService {
	private WriteArticleDAO writeArticleDAO;
    
    //생성자 (생성자를 통해 객체 전달)
    public WriteArticleService(WriteArticleDAO writeArticleDAO){
    	this.writeArticleDAO = writeArticleDAO;
    }
    
    public void write(){
    	System.out.println("WriteArticleService의 write() 메서드 실행");
        
        writeArticleDAO.insert();
    }
}

public WriteArticleService(WriteArticleDAO writeArticleDAO) 처럼

의존관계를 넣는 것을 의존관계를 주입한다(DI) 라고 함 

 

 

 

 

설정파일에 명시

applicationContext.xml

<bean name="writeArticleService" class="kr.spring.ch04.WriteArticleService">
	<constructor-arg>
    	<ref bean="writeArticleDAO"/>
    </constructor-arg>
</bean>
<bean name="writeArticleDAO" class="kr.spring.ch04.WriteArticleDAO" />

의존관계가 아닌 것은 단독bean태그

의존관계인것은 bean태그 사이에 의존관계를 주입해야함

 

<constructor-arg> 생성자의 인자에 의존 객체 전달

<ref> 주입할 의존 객체를 지정, bean 속성에 주입할 의존 객체 식별자 명시

 

 

 

 

출력 메인

kr.spring.ch04

SpringMain

package kr.spring.ch04;

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

public class SpringMain {
	public static void main(String[] args){
    	/*
		 * applicationContext.xml 설정 파일을 읽어들여 스프링 컨테이너를 생성
		 */
         AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
         
         //컨테이너에 DI 생성자 설정방식으로 생성된 객체를 읽어들임
         WriteArticleService articleService = (WriteArticleService)context.getBean("writeArticleService");
         
         articleService.write();
         
         //어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
         context.close();
    }
}
[출력결과]

WriteArticleService의 write()메서드 실행
WriteArticleDAO의 insert() 메서드 실행

 

 

 


 
 
 
생성자 방식 연습2
 
 

의존적이지 않은 클래스

kr.spring.ch05

MemberDAO 

package kr.spring.ch05;

public class MemberDAO{
	public void register(){
    	System.out.println("MemberDAO의 register() 메서드 실행");
    }
}

 

 

 

 

 

MemberDAO에 의존적인 클래스

kr.spring.ch05

MemberService

package kr.spring.ch05;

public class MemberService {
	private MemberDAO memberDAO;
    
    //생성자
    public MemberService(MemberDAO memberDAO) { //의존관계 주입(memberDAO)
    	this.memberDAO = memberDAO;
    }
    
    public void send(){
    	System.out.println("MemberService의 send() 메서드 실행");
        
        memberDAO.register();
    }
}

 

 

 

 

 

설정파일

applicationContext.xml

<bean name="memberService" class="kr.spring.ch05.MemberService">
	<constructor-arg>
    	<ref bean="memberDAO"/>
    </constructor-arg>
</bean>
<bean name="memberDAO" class="kr.spring.ch05.MemberDAO"/>

 

 

 

 

출력 파일

kr.spring.ch05

SpringMain

package kr.spring.ch05;

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

public class SpringMain {
	public static void main(String[] args) {
		/*
		 * applicationContext.xml 설정 파일을 읽어들여 스프링 컨테이너를 생성
		 */
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		//컨테이너에 DI 생성자 설정방식으로 생성된 객체를 읽어들임
		MemberService memberService = (MemberService)context.getBean("memberService");
		
		memberService.send();
		
		//어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
		context.close();
		
	}
}

[출력결과]
MemberService의 send() 메서드 실행
MemberDAO의 register() 메서드 실행

 

 

 


 

 

 

복수의 생성자 개수 연습 (인자 2개)

kr.spring.ch06

SmsSender

package kr.spring.ch06;

public class SmsSender{
	@Override
    public String toString(){
    	return "SmsSender 호출";
    }
}

 

toString 재정의

 

 

 

 

 

의존관계인 클래스

kr.spring.ch06

SystemMonitor

package kr.spring.ch06;

public class SystemMonitor {
	private long periodTime;
    private SmsSender sender;
    
    //생성자
    public SystemMonitor(long periodTime, SmsSender sender){
    	this.periodTime = periodTime;
        this.sender = sender;
    }
    
    @Override
	public String toString() {
		return "SystemMonitor [periodTime=" + periodTime + ", sender=" + sender + "]";
	}
}

source -> generate to String 사용

 

 

 

설정파일

applicationContext.xml

<bean id="monitor" class="kr.spring.ch06.SystemMonitor">
	<constructor-arg>
    	<value>10</value>  <!-- 숫자,문자열은 설정파일에 명시해야함 -->
    </constructor-arg>
    <constructor-arg>
    	<ref bean="smsSender"/>
    </constructor-arg>
</bean>
<bean id="smsSender" class="kr.spring.ch06.SmsSender"/>

DI 생성자 설정방식 시 bean태그 name = id 같아서 아무거나 써도 됨

의존관계 설정 시 인자의 순서대로 기재 해야함

숫자, 문자열은 설정파일에 value로 명시해야 함

 

long 타입을 직접 명시할 수도 있음

<value type="long">10</value>

 

인자가 여러 개면 xml 파일에서 constructor-arg가 증가함

value(숫자, 문자열)은 클래스가 정의되고 숫자를 만드는 게 아니라 그냥 설정파일에 바로 명시하는 방법을 씀

 

 

 

 

출력 파일

kr.spring.ch06

SpringMain

package kr.spring.ch06;

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

public class SpringMain {
	public static void main(String[] args) {
		/*
		 * ApplicationContext.xml 설정파일을 읽어들여 스프링 컨테이너를 생성
		 */
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//DI 생성자 방식 - 인자를 여러개 전달
		SystemMonitor monitor = (SystemMonitor)context.getBean("monitor");
		
		System.out.println(monitor); //toString을 출력하면 됨
		
		//어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
		context.close();
	}
}

[출력결과]
SystemMonitor [periodTime=10, sender=SmsSender 호출]

 

 

 


 

 

위 방법뿐만 아니라 다른 설정 방법들도 있음

설정파일

applicationContext.xml

<!-- 속성으로 값 또는 객체 설정 -->
<constructor-arg value="20"/>
<constructor-arg ref="smsSender"/>
<!-- [출력화면]
SystemMonitor [periodTime=20, sender=SmsSender 호출] -->


<!-- 인자 순서를 무시할 때는 index 표시 -->
<constructor-arg ref="smsSender" index="1"/>
<constructor-arg value="30" index="0"/>
<!-- [출력화면]
SystemMonitor [periodTime=30, sender=SmsSender 호출] -->


<!-- 생성자의 인자명 기재 (SystemMonitor의 인자명) -->
<constructor-arg name="periodTime" value="40"/>
<constructor-arg name="sender" ref="smsSender"/>
<!-- [출력화면]
SystemMonitor [periodTime=40, sender=SmsSender 호출] -->

 

 

 


 

 

 

 

프로퍼티 방식

 

 

의존관계가 없는 클래스

kr.spring.ch07

RegisterDAO

package kr.spring.ch07;

public class RegisterDAO {
	public void insert(){
    	System.out.println("RegisterDAO의 insert() 메서드 실행");
    }
}

 

 

 

 

의존관계가 있는 클래스

kr.spring.ch07

RegisterService

package kr.spring.ch07;

public class RegisterService {
	private RegisterDAO registerDAO;

	public void setRegisterDAO(RegisterDAO registerDAO) {
		this.registerDAO = registerDAO;
	}
	
	public void write() {
		System.out.println("RegisterService의 write() 메서드 실행");
		registerDAO.insert();
	}
}

 

오타 방지를 위해
source -> generate getters and setters -> select setters -> generate

 

아까는 생성자를 만들었는데 지금은 set메서드를 만들었음

private일 경우에는 public한 메서드를 만들어서 자바빈처럼 똑같이 set메서드를 만들어서 사용함

데이터를 전달받을 수 있는 public한 메서드를 생성하는 방식 = 프로퍼티 방식

 

 

 

 

설정파일

applicationContext2.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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        
	<!-- DI 프로퍼티 설정방식 -->
	<bean name="registerService" class="kr.spring.ch07.RegisterService">
		<!-- set registerDAO에 전달해야함 -->
		<!-- name : 의존 객체를 주입할 때 사용할 설정 메서드의 프로퍼티 이름 -->
		<property name="registerDAO"><!-- private RegisterDAO registerDAO; 의 뒷부분 명시 (근데 접근은 public만 가능하므로 아래에 넣음) -->
			<!-- ref : 주입할 의존 객체 지정 -->
			<ref bean="registerDAO"/>
		</property> 
	</bean>
	<bean name="registerDAO" class="kr.spring.ch07.RegisterDAO"/>
        
</beans>

 

<property name="registerDAO"> == <bean name="registerDAO" class="kr.spring.ch07.RegisterService"> == ch07.RegisterService 프로퍼티명

 

<ref bean="registerDAO"/> == <bean name="registerDAO" class="kr.spring.ch07.RegisterDAO"/>

 

 

 

 

메인클래스

kr.spring.ch07

SpringMain

package kr.spring.ch07;

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

public class SpringMain {
	public static void main(String[] args) {
		/*
		 * applicationContext2.xml의 설정파일을 읽어들여 스프링 컨테이너를 생성
		 */
		AbstractApplicationContext context =
				new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		//DI 프로퍼티 설정방식으로 생성된 객체 호출
		RegisterService service = (RegisterService)context.getBean("registerService");
		service.write();
		
		//어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
		context.close();
		
	}
}

 

[출력결과]

RegisterService의 write() 메서드 실행

RegisterDAO의 insert() 메서드 실행

 

 

 


 

 

 

 

프로퍼티 연습2

(프로퍼티 + 인자 2개)

 

 

 

의존관계가 없는 클래스

kr.spring.ch08

EmailSender 

package kr.spring.ch08;

public class EmailSender {

	@Override
	public String toString() {
		return "EmailSender 호출";
	}
}

 

 

 

 

의존관계가 있는 클래스

kr.spring.ch08

WorkController

package kr.spring.ch08;

public class WorkController {
	private long periodTime;
    private EmailSender email;
    
	public void setPeriodTime(long periodTime) {
		this.periodTime = periodTime;
	}
	public void setEmail(EmailSender email) {
		this.email = email;
	}
    
	@Override
	public String toString() {
		return "WorkController [periodTime=" + periodTime + ", email=" + email + "]";
	}
}

 

 

 

 

 

설정파일

applicationContext2.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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        
	<!-- DI 프로퍼티 설정방식 - 여러 개의 프로퍼티 -->
	<bean id="work" class="kr.spring.ch08.WorkController">
		<property name="periodTime">
			<value>10</value>
		</property>
		<property name="email"> <!-- 프로퍼티명 -->
			<ref bean="email"/> <!-- 식별자 -->
		</property>
	</bean>
	<bean id="email" class="kr.spring.ch08.EmailSender"/> <!-- 식별자 -->
</beans>

 

 

 

 

메인클래스

kr.spring.ch08

SpringMain

package kr.spring.ch08;

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

public class SpringMain {
	public static void main(String[] args) {
		/*
		 * applicationContext2.xml 설정파일을 읽어들여 스프링 컨테이너를 생성
		 */
		AbstractApplicationContext context =
				new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		//DI 프로퍼티 설정방식 - 여러개의 프로퍼티
		WorkController work = (WorkController)context.getBean("work");
		System.out.println(work);
		
		//어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
		context.close();
	}
}

 

 

[출력화면]

WorkController [periodTime=10, email=EmailSender 호출]

 

 


 

 

applicationContext2.xml

xmlns:p="http://www.springframework.org/schema/p"

(namespace) 를 이용해서 프로퍼티 설정을 줄여서 지정해볼 것임

 

 

 

의존관계가 없는 클래스

kr.spring.ch09

ImageSender

package kr.spring.ch09;

public class ImageSender {

	@Override
	public String toString() {
		return "ImageSender 호출";
	}
	
}

 

 

 

 

의존관계가 있는 클래스

kr.spring.ch09

UploadController

package kr.spring.ch09;

public class UploadController {
	private long timeout;
    private ImageSender image;
	
	public void setTimeout(long timeout) {
		this.timeout = timeout;
	}
	public void setImage(ImageSender image) {
		this.image = image;
	}
	
	@Override
	public String toString() {
		return "UploadController [timeout=" + timeout + ", image=" + image + "]";
	}
}

 

 

 

 

설정파일

applicationContext2.xml

(p ns를 이용, 간단하게 프로퍼티 설정)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        
        <!-- XML 네임스페이스를 이용한 프로퍼티 설정 -->
        <bean id="upload" class="kr.spring.ch09.UploadController" 
        	p:timeout="50" p:image-ref="image"/>
            <!-- 일반 데이터 넘길 시 timeout // 객체 전달 시 -ref를 사용, 객체 전달이라는걸 알려줘야함 -->
        <bean id="image" class="kr.spring.ch09.ImageSender"/>
        
</beans>

p:property의 약자

객체 전달 시 -ref 사용

 

 

 

 

메인클래스

kr.spring.ch09

SpringMain

package kr.spring.ch09;

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

public class SpringMain {
	public static void main(String[] args) {
		/*
		 * applicationContext2.xml 설정파일을 읽어들여 스프링 컨테이너를 생성
		 */
		AbstractApplicationContext context =
				new ClassPathXmlApplicationContext("applicationContext2.xml");
		
		//XML 네임스페이스를 이용한 프로퍼티 설정
		UploadController upload = (UploadController)context.getBean("upload");
		System.out.println(upload);
		
		//어플리케이션 종료시 컨테이너에 존재하는 모든 빈(객체)를 종료
		context.close();
	}
}

 

[출력결과]

UploadController [timeout=50, image=ImageSender 호출]

728x90
반응형