의존성 주입(dependency injection)은 하나의 객체가 다른 객체의 의존성을 제공하는 테크닉이다.
즉, 외부에서 두 객체 간의 관계를 지정해주는 디자인 패턴으로, 인터페이스를 사이에 두어 클래스 레벨에서는
의존관계가 고정되지 않도록 하고, 서버 런타임 시 관계를 동적으로 주입하여 결합도를 떨어트릴 수 있게 해준다.
의존성 주입에는 크게 두가지 방법이 있다.
1) 생성자 인젝션
2) 수정자(Setter) 인젝션
1) 생성자 인젝션
Iphone의 기본생성자 외에 Watch와 battery를 인자로 필요로 하는 생성자를 만든다.
그리고 .xml 파일 ( 스프링 컨테이너 ) 에는
Galaxy 객체를 phone에 담고, 이 때 이 멤버변수는
ref = "주입할 객체명"
value= "문자열 혹은 기본형 데이터"
를 주입할 수 있다.
생성자 주입은 먼저 생성자의 인자에 사용될 빈을 찾거나 빈 팩토리에서 만든다. ( bean id="gw" )
그 후에 찾은 인자 빈으로 주입하려는 빈의 생성자를 호출하여 사용한다.
즉, 먼저 빈을 생성하는 것이 아니라 주입하려는 빈을 먼저 찾는다.
2) 수정자 인젝션 (setter)
위와 같이 들어가는 멤버변수가 정해져있는 상태라면
생성자 인젝션이 OOP중 OCP(Open-Closed Principal, 개방-폐쇄 원칙)에 위반되지 않고,
불변성을 보장하기 때문에 더 유용하겠지만,
인자들의 값이 변경될 수 있기 때문에 수정자 인젝션을 사용하는 법도 알아야 한다 생각한다.
위에 예를 이어서 설명하자면 , 폰은 갤럭시 폰인데 다른 워치를 사용할 수도 있을 것이다.
이 때, Watch의 종류 혹은 배터리의 상태는 변한 객체를 만들어야하기 때문에 setter 인젝션을 사용하는 것이다.
다음과 같이 private 된 멤버변수들을 getter와 setter를 만들어
watch를 aw ( appleWatch 로 만든 bean) battery를 70으로 넣어준다.
p네임스페이스 사용법
1. xml 파일을 연다
2. 하단에 Namespaces 탭을 누른다
3. p 태그 체크해서 활성화
4. 하단과 같이 xml 상단에 추가된 것을 볼 수 있다.
p:멤버변수명-ref = "주입할 객체명"
p:멤버변수명 = "주입할 값"
으로 사용하면 된다.
뿐만 아니라, 객체의 멤버변수로 컬렉션 또한 사용 가능한데
List 컬렉션으로 선언 된 datas와
Map 컬렉션으로 선언 된 datas1을 멤버변수로 만들고
list를 사용하여 data에 set 해줄 수 있고,
컬렉션 Set 또한 다음과 같이 사용 가능하며
컬렉션 Map도 다음과 같이 사용 가능하다.
출력을 위해 main이 존재하는 클래스를 만들면
다음과 같이 작성할 수 있으며, factory.close는 모든 수행이 다 되었을 때만 써주면 된다.
( 한번에 출력을 보고 싶으면 중간에 factory.close() 2개는 지우고 최하단 factory.close만 남기면 됨 )
출력결과
전체코드
Client.java
package test;
import java.util.Map;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class Client {
public static void main(String[] args) {
// Spring 컨테이너를 동작시킬수있도록 코드작성
AbstractApplicationContext factory=new GenericXmlApplicationContext("applicationContext.xml");
TestBean tb=(TestBean)factory.getBean("tb");
for(String v:tb.getDatas()) {
System.out.println(v);
}
//factory.close();
TestBean tb2=(TestBean)factory.getBean("tb2");
for(String v:tb2.getDatas()) {
System.out.println(v);
}
// factory.close();
TestBean tb3=(TestBean)factory.getBean("tb3");
Map<String,String> datas=tb3.getDatas1();
System.out.println(datas);
factory.close();
// Spring 컨테이너야, 나 폰 객체를 가지고싶어!
// == Lookup
//Phone phone=(Phone)factory.getBean("gp");
//phone.powerOn();
//phone.powerOff();
//factory.close();
/*
BeanFactory bf=new BeanFactory();
Phone phone=(Phone)bf.getBean(args[0]);
phone.powerOn();
phone.volumeUp();
phone.volumeDown();
phone.powerOff();
*/
}
}
applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="phone" class="test.Galaxy" init-method="initMethod" destroy-method="destroyMethod" lazy-init="true" >
<property name="watch" ref="aw"/> <!-- 객체는 ref -->
<property name="battery" value="70" /> <!-- 값은 value -->
</bean>
<bean id="gp" class="test.Galaxy" p:watch-ref="gw" p:battery="70" /> <!-- p 네임스페이스로도 세터가능 -->
<bean id="iphone" class="test.IPhone" lazy-init="true" />
<bean id="aw" class="test.AppleWatch" />
<bean id="gw" class="test.GalaxyWatch" />
<bean id="tb" class="test.TestBean">
<property name="datas">
<list>
<value>서울시</value>
<value>서울시 관악구</value>
<value>사당역</value>
</list>
</property>
</bean>
<bean id="tb2" class="test.TestBean">
<property name="datas">
<set>
<value>바나나</value>
<value>바나나</value> <!-- set은 중복이 제거된 집합이다. -->
<value>키위</value>
</set>
</property>
</bean>
<bean id="tb3" class="test.TestBean">
<property name="datas1">
<map>
<entry>
<key><value>아리</value></key>
<value>미드</value>
</entry>
<entry>
<key><value>아무무</value></key>
<value>서포터</value>
</entry>
<entry>
<key><value>티모</value></key>
<value>탑</value>
</entry>
</map>
</property>
</bean>
</beans>
여러 폰 중 하나 IPhone ( 인터페이스 Phone을 implements )
package test;
public class IPhone implements Phone{
private Watch watch;
private int battery;
public IPhone() {
System.out.println("아이폰 객체생성완료");
}
public IPhone(Watch watch, int battery) {
this.watch=watch;
this.battery=battery;
}
@Override
public void powerOn() {
System.out.println("아이폰 전원 ON");
}
@Override
public void powerOff() {
System.out.println("아이폰 전원 OFF");
}
public Watch getWatch() {
return watch;
}
public void setWatch(Watch watch) {
this.watch = watch;
}
public int getBattery() {
return battery;
}
public void setBattery(int battery) {
this.battery = battery;
}
}
Watch를 implement 하는 GalaxyWatch
package test;
public class GalaxyWatch implements Watch{
@Override
public void volumeUp() {
System.out.println("갤워치 소리 ++");
}
@Override
public void volumeDown() {
System.out.println("갤워치 소리 ++");
}
}
'개발자노트 > Spring' 카테고리의 다른 글
Spring AOP Joinpoint 바인드 변수 (0) | 2022.09.16 |
---|---|
AOP 용어 정리 (0) | 2022.09.15 |
Spring AOP ( 관점지향 프로그래밍 ) (0) | 2022.09.13 |
Spring 개념 IOT ( 제어의 역행 ) (0) | 2022.09.13 |
이클립스에서 Spring 프레임워크 [플러그인] 사용하기 (0) | 2022.09.13 |