본문 바로가기
Spring/Spring

day61) 생성자 injection, setter injection

by code_learner 2022. 3. 29.

IoC를 지원하는 컨테이너에게 객체생성권을 줄수있으니, 이를 이용해보자!

객체들을 생성하여 작업하다보면, "의존관계"가 발생한다.
Dependency -> Dependency Injection(DI,의존성 주입)★☆★☆★
(원시타입보다 객체를 대상)

 

[설계]

인터페이스로 같은 메서드를 사용하게 강제한다.

TV 인터페이스 - 전원 on, off , 볼륨 up, down

Remote 인터페이스 - 볼륨 up, down

-> 리모콘으로 볼륨 up, down을 하며 A, B어느 걸로 하던 상관없이 작동한다

-> LgTV는 생성자 injection, SamsungTV는 setter injection으로 리모콘의 의존성을 주입할 예정 

 

[코드]

TV인터페이스

package test;

public interface TV {
	public void powerOn(); 
	public void powerOff(); 
	public void volumeUp(); 
	public void volumeDown();
}

 

LgTV(생성자 injection)

package test;

public class LgTV implements TV{
	private Remote remote;
	private int tvid;
	public LgTV() {
		System.out.println("LgTV 객체 생성");
	}
	public LgTV(Remote remote) {
		//생성자를 통해 의존관계에 있는 객체를 주입
		//생성자 주입(생성자 인젝션)
		System.out.println("LgTV 객체 생성22");
		this.remote = remote;
	}
	public LgTV(Remote remote, int tvid) {
		System.out.println("LgTV 객체 생성33");
		this.remote = remote;
		this.tvid=tvid;
	}
   public void powerOn() {
      System.out.println("전원 ON tvid:"+tvid);
   }
   public void powerOff() {
      System.out.println("전원 OFF tvid:"+tvid);
   }
   public void volumeUp() {
	   remote.volumeUp();
   }
   public void volumeDown() {
	   remote.volumeDown();
   }
}

SamsungTV(setter injection)

package test;

public class SamsungTV implements TV {
   private Remote remote;
   private int tvid;
   public SamsungTV() {
      System.out.println("SamsungTV 객체생성");
   }
   
   public Remote getRemote() {
      return remote;
   }

   public void setRemote(Remote remote) {
      this.remote = remote;
   }

   public int getTvid() {
      return tvid;
   }

   public void setTvid(int tvid) {
      this.tvid = tvid;
   }
   // ★ setter 주입

   public void initMethod() {
      System.out.println("객체의 멤버변수들 초기화 작업");
   }
   public void destroyMethod() {
      System.out.println("객체 메모리 해제 작업");
   }
   @Override
   public void powerOn() {
      System.out.println("전원을 켭니다.");
   }
   @Override
   public void powerOff() {
      System.out.println("전원을 끕니다.");
   }
   @Override
   public void volumeUp() {
      remote.volumeUp();
   }
   @Override
   public void volumeDown() {
      remote.volumeDown();
   }
}

리모콘 인터페이스

package test;

public interface Remote {
	public void volumeUp();
	public void volumeDown();
}

리모콘A

package test;

public class RemoteA implements Remote{
	public RemoteA() {
		System.out.println("A리모컨 생성완료");
	}
	public void volumeUp() {
		System.out.println("A: 소리UP");
	}

	public void volumeDown() {
		System.out.println("A: 소리DOWN");
	}
}

리모콘B

package test;

public class RemoteB implements Remote{
	
	public RemoteB() {
		System.out.println("B리모컨 생성완료");
	}
	@Override
	public void volumeUp() {
		
		System.out.println("B: 소리UP");
	}

	@Override
	public void volumeDown() {
		System.out.println("B: 소리Down");
		
	}
	
}

applicationContext

	<bean class="test.LgTV" id="tv1"> 생성자 주입
		<constructor-arg ref="rA"/> <!--tv객체의 인자로 remote객체 전달--> 
		<constructor-arg value="1001"/>  <!--원시 타입을 인자로 줄 때는 value속성 이용 --> 
	</bean> 
	
    <bean class="test.SamsungTV" id="tv2">
		<property name="remote" ref="rB"/> <!--멤버변수 이름과 동일하게 연결해야함-->
		<property name="tvid" value="1002"/><!-- setter는 property속성 사용-->
	</bean>
    
	<bean class="test.RemoteA" id = "rA" lazy-init="true"/> remote객체 생성 
	<bean class="test.RemoteB" id = "rB" lazy-init="true"/>

Client

//0. Spring 컨테이너를 실행시킬 때 필요한 설정정보파일(==applicationContext.xml) 생성햇기 때문에 1번가능!
//1. Spring 컨테이너를 실행시킴
//LgTV,SamsungTV의 객체를 컨테이너가 생성한다.
AbstractApplicationContext factory=new GenericXmlApplicationContext("applicationContext.xml");

		TV tv=(TV)factory.getBean("tv1");
		tv.powerOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.powerOff();
        
        //tv1-> lgTV, tv2 -> samsungTV

 

 

[객체 생성 시점]
1)생성자 주입
B -> TV
new RemoteB();
new TV(remoteB);

2)setter주입
new TV();//기본생성자를 만들어 tv공간을 만든 후
new RemoteB();
tv.setRemote(remoteB); //setter()메서드들을 호출

댓글