12.27 (DI, 컨테이너 생성-프로퍼티 방식, 인자 2개)
<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() 메서드 실행
의존적이지 않은 클래스
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 호출]