DI의 개요
필요로하는 객체를 만들어서 원하는 위치에 자동으로 주입(injection)하는 기능으로
생성자 또는 Setter Method를 통해서 저장한 객체를 멤버변수에 저장한다.
다시말해 의존성 객체를 특정한 위치에 알아서 넣어주는 기능이다.
DI를 사용하는 예제통해 정리하고자 한다.
DI를 사용한 예제
1.인터페이스 생성 => MessageBeanDI
공통으로 사용하는 추상메서드를 선언하여 인터페이스로 만든다.
package spring2
//공통으로 사용하는 메서드를 선언(추상메서드)
public interface MessageBeanDI {
public void sayHello();// OutFile -> out()
}
2.위의 인터페이스(MessageBeanDI)를 상속받는 자식클래스 생성
=> MessageBeanImplDI.java
공통으로 사용되는 인터페이스를 상속받은 클래스를 생성하되 멤버변수들을 각각 생성자와 Setter 메서드를 통해 저장하도록 할려한다.
package spring2;
public class MessageBeanImplDI implements MessageBeanDI {
//DI를 이용해서 객체를 가져와서 넣어주는 방법(멤버변수에 넣어준다)
private String name1,name2;// 생성자를 통해서 저장(constructor injection)
private String greeting;//Setter Method를 통해서 (Setter Injection)
}
3. 생성자 인젝션 (constructor injection)
위의 멤버변수중 private String name1,name2를 생성자를 통해서 저장하고자 한다.
이클립스 소스를 사용하면 간편히 만들수있음
//1.<constructor-arg>태그를 이용해서 값을 임의로 지정해서 저장
public MessageBeanImplDI(String name1, String name2) { // 생성자 생성
this.name1 = name1;
this.name2 = name2;
System.out.println("MessageBeanImplDI 생성자호출됨");
}
4.Setter 인젝션 (Setter Injection)
남은 멤버변수인 private String greeting을 Setter Method를 통해서 저장하고자 한다.
이클립스 소스를 사용하면 간편히 만들수있음
//2.<property>태그를 이용해서 호출->임의 값을 전달
public void setGreeting(String greeting) { //setter 메서드생성
this.greeting = greeting;
System.out.println("setGreeting() 호출됨!");
}
받아온 인터페이스의 추상메서드에 문구 출력
@Override
public void sayHello() {
// TODO Auto-generated method stub
String message=greeting+name1+","+name2+"!";
System.out.println("message=>"+message);
이제 생성자와 Setter메서드의 객체를 주입하기 위해서 객체(Bean) 생성하기위한 환경설정파일인 xml을 만든다.
5.xml파일생성
우선 Bean으로 묶어준 후 객체를 구별하기 위한 아이디값과 패키지명.클래스명을 부여한다.
형식) <bean id="객체를 구분하는 인자번호" class="패키지명..클래스명"/>
<bean id="mBean" class="spring2.MessageBeanImplDI">
1)생성자가 있어서 xml문법으로 생성자를 호출해야한다.
<bean id="mBean" class="spring2.MessageBeanImplDI">
<constructor-arg index="0">
<value>대한민국</value>
</constructor-arg>
<constructor-arg index="1">
<value>서울</value>
</constructor-arg>
</bean>
여기서 value를 contructor-arg안에 넣고 생략할수도 있다.
<constructor-arg index="0">
<value>대한민국</value>
</constructor-arg>
이것을 이렇게
=> <constructor-arg index="0" value="대한민국" />
2)Setter 메서드 호출은 property를 사용한다.
<property name="greeting">
<value>안녕,</value>
</property>
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-4.3.xsd">
<!-- 생성자가 있어서 xml문법으로 생성자를 호출해야함=> constructor-arg을 사용(매개변수있는만큼) -->
<!-- index속성값을 부여해서 매개변수의 순서를 정할수있다 (안쓰면 순서대로) -->
<!-- 매개변수로 문자열과 숫자를 넘겨줄때 value -->
<!--property는 Setter 메서드 호출 -->
<bean id="mBean" class="spring2.MessageBeanImplDI">
<constructor-arg index="0">
<value>대한민국</value>
</constructor-arg>
<constructor-arg index="1">
<value>서울</value>
</constructor-arg>
<property name="greeting">
<value>안녕,</value>
</property>
</bean>
</beans>
여기까지 하고 HelloApp를 실행하면
=> 안녕,대한민국,서울! 이 콘솔창에 출력한다.
여기서 실행시키면 그 결과를 저장하는 파일을 만드면서 동시에 출력해주고싶으면?
문자열을 출력시켜주는 파일 추가
문자열을 출력시켜주는 파일 추가하기
=> 실행하면 파일을 만들고 문자열을 출력할거면?
1.인터페이스 생성 => OutFile
package spring2;
import java.io.IOException;
//파일에 문자열을 입력받아서 출력시켜주는 공통의 추상메서드
public interface OutFile {
public void out(String message)throws IOException;
}
2. 위의 인터페이스(OutFile)를 상속받는 자식클래스 생성
=>OutFileImpl.java
경로명 및 만들어진 파일명을 저장하는 멤버변수를 만들고 Setter Method를 생성
public class OutFileImpl implements OutFile {
private String filePath; //경로명 및 만들어진 파일명 저장 /Setter Method로
//setFilePath()호출하기 위해서 <property>태그를 줘야 된다.
public void setFilePath(String filePath) {
this.filePath = filePath;
System.out.println("setFilePath()호출됨=>"+filePath);
}
받아온 인터페이스의 추상메서드에 받아오는 한글문구를 출력해주는 객체를 경로를 담는 변수를 포함해서 생성
@Override
public void out(String message) throws IOException {
// TODO Auto-generated method stub
//한글데이터 저장->FileOutputStream(영문),FileWriter(한글)
FileWriter fw=new FileWriter(filePath);//c:/webtest/good.txt 경로를 filePath에 저장
fw.write(message);
fw.close(); //메모리해제 종류
}
종합하면
OutFileImpl.java
package spring2;
import java.io.*;
//파일을 생성->파일내부에 문자열을 출력시켜주는 프로그램
public class OutFileImpl implements OutFile {
private String filePath; //경로명 및 만들어진 파일명 저장 /Setter Method로
//setFilePath()호출하기 위해서 <property>태그를 줘야 된다.
public void setFilePath(String filePath) {
this.filePath = filePath;
System.out.println("setFilePath()호출됨=>"+filePath);
}
@Override
public void out(String message) throws IOException {
// TODO Auto-generated method stub
//한글데이터 저장->FileOutputStream(영문),FileWriter(한글)
FileWriter fw=new FileWriter(filePath);//c:/webtest/good.txt 경로를 filePath에 저장
fw.write(message);
fw.close(); //메모리해제 종류
}
}
3.xml에 내용 추가
새로운 Bean을 생성해서 OutFileImpl에서의 Setter 메서드 객체를 설정
value값을 경로를 쓴다 => filePath는 경로를 저장하는 멤버변수로 설정해주자
<!-- outFileImpl -->
<bean id="outFile" class="spring2.OutFileImpl">
<property name="filePath">
<value>c:/webtest/good.txt</value>
</property>
</bean>
4. MessageBeanImplDI.java 에 OutFile의 객체를 불러온다
MessageBeanImplDI.java 에 OutFile의 객체를 불러온다 (인터페이스로 불러온다)
=>연결된 다른 클래스내용을 가능한 덜 수정할 수 있도록 인터페이스를 불러서 사용 (결합도를 낮춤)
불러온 인터페이스부분에 OutF객체를 이용해서 out(message)호출하는것을 추가
최종 MessageBeanImplDI.java
package spring2;
public class MessageBeanImplDI implements MessageBeanDI {
//DI를 이용해서 객체를 가져와서 넣어주는 벙법(멤버변수에 넣어준다)
private String name1,name2;// 생성자를 통해서 저장(constructor injection)
private String greeting;//Setter Method를 통해서 (Setter Injection)
//------------has 관계(의존관계)--------------------
private OutFile outF;// private OutFileImpl outF; (X) 이렇게하면 결합도가 높아 불편
//수정=> 연결된 다른 클래스내용을 가능한 덜 수정할 수 있도록 인터페이스를 사용하기 때문에
public void setOutF(OutFile outF) {//OutFileImpl(형변환)
this.outF = outF;
System.out.println("setOutF()호출됨=>"+outF);
}
//1.<constructor-arg>태그를 이용해서 값을 임의로 지정해서 저장
public MessageBeanImplDI(String name1, String name2) { // 생성자 생성
this.name1 = name1;
this.name2 = name2;
System.out.println("MessageBeanImplDI 생성자호출됨");
}
//2.<property>태그를 이용해서 호출->임의 값을 전달
public void setGreeting(String greeting) { //setter 메서드생성
this.greeting = greeting;
System.out.println("setGreeting() 호출됨!");
}
@Override
public void sayHello() {
// TODO Auto-generated method stub
String message=greeting+name1+","+name2+"!";
System.out.println("message=>"+message);
//OutF객체를 이용해서 out(message)호출
try {//입출력에선 try catch를 사용
outF.out(message); // message의 내용을 c:/webtest/good.txt를 만들면서 출력해준다
}catch(Exception e) {
e.printStackTrace();
}
//-----------------------------------------------
}
}
<property name="outF" ref="outFile">
</property>
ref를 밖으로 빼서 작성할수도있다
=> <property name="outF">
<ref bean="outFile" />
</property>
최종 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-4.3.xsd">
<!-- 생성자가 있어서 xml문법으로 생성자를 호출해야함=> constructor-arg을 사용(매개변수있는만큼) -->
<!-- index속성값을 부여해서 매개변수의 순서를 정할수있다 (안쓰면 순서대로) -->
<!-- 매개변수로 문자열과 숫자를 넘겨줄때 value -->
<!--property는 Setter 메서드 호출 -->
<bean id="mBean" class="spring2.MessageBeanImplDI">
<constructor-arg index="0" value="대한민국" />
<!-- <value>대한민국</value>
</constructor-arg> -->
<constructor-arg index="1">
<value>서울</value>
</constructor-arg>
<property name="greeting">
<value>안녕,</value>
</property>
<!-- <property name="outF" ref="outFile"> -->
<property name="outF">
<ref bean="outFile" />
</property>
</bean>
<!--위와 아래 클래스를 연결하기 위해 밑에 outFile을 위에 새로만든 outF에 넣어준다 (ref 사용) -->
<!--직접적으로 ref를 안쓴다면 property 안에 ref bean으로 따로 만들어준다. -->
<!-- 마찬가지로 위에 value값도 안에 넣어서 간단히 생략가능하다 -->
<!-- outFileImpl -->
<bean id="outFile" class="spring2.OutFileImpl">
<property name="filePath">
<value>c:/webtest/good.txt</value>
</property>
</bean>
</beans>
이렇게 작성 후 실행하면 자동으로 동시에 파일을 만들고 그 안에 값을 출력하고 저장한다
2022-08-18
머리가 터질거같아요