8. Setter Injection vs Constructor Injection
생성자 주입은 컴포넌트를 사용하기 전에 의존 해야하는 클래스의 인스턴스를 가지고 있어야 할 때 유용하며 세터주입은 부모 컴포넌트의 새 인스턴스를 생성하지 않고 동적으로 각기 다른 구현을 사용해 의존성을 대체할 수 있다. 즉 의존성을 인터페이스로 선언할 수 있다는 점이 장점이며 덜 강압적인 주입이라 할 수 있다.
기본 생성자만 있는 클래스에 생성자 주입을 정의하면 비 IoC 환경에서 해당 클래스를 사용하는 모든 클래스에 영향을 주게 된다. 하지만 세터 주입의 경우 다른 클래스가 이 클래스와 상호작용 하는데 있어 영향을 덜 주게 된다.
일반적으로 세터 주입을 이용하는 것이 좋다.
이 방식은 비 IoC 설정에서 코드를 사용하는데 최소한의 영향만을 주기 때문이다. 생성자 주입은 컴포넌트로 항상 의존성이 전달되게 할 때 적합하다.
9. DI(Dependency Injection)
1. Setter Injection(XML 기반)
Emp
package ioc.ioc5;
interface Emp {
public void gotoOffice();
public void getofWork();
}
Programmer
package ioc.ioc5;
public class Programmer implements Emp{
public void gotoOffice() {
System.out.println("프로그래머 출근합니다.");
}
public void getofWork() {
System.out.println("프로그래머 퇴근합니다.");
}
}
Designer
package ioc.ioc5;
public class Designer implements Emp{
public void gotoOffice() {
System.out.println("디자이너 출근합니다.");
}
public void getofWork() {
System.out.println("디자이너 퇴근합니다.");
}
}
Develope
package ioc.ioc5;
import org.springframework.stereotype.Service;
@Service
public class Develope {
private Emp emp;
public void setEmp(Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("업무합니다....");
emp.getofWork();
}
}
ioc.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="ioc.ioc5.Programmer" id="programmer" />
<bean class="ioc.ioc5.Designer" id="designer" />
<bean class="ioc.ioc5.Develope" id="develope" p:emp-ref="programmer" />
</beans>
TestMain
package ioc.ioc5;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ioc5.xml");
Develope dev = (Develop)context.getBean("develope");
dev.coding();
}
}
2. Constructor Injection(XML 기반)
Emp
package ioc.ioc6;
public interface Emp {
public void gotoOffice();
public void getofWork();
}
Programmer
package ioc.ioc6;
public class Programmer implements Emp{
public void gotoOffice() {
System.out.println("프로그래머 출근합니다.");
}
public void getofWork() {
System.out.println("프로그래머 퇴근합니다.");
}
}
Designer
package ioc.ioc6;
public class Designer implements Emp{
public void gotoOffice() {
System.out.println("디자이너 출근합니다.");
}
public void getofWork() {
System.out.println("디자이너 퇴근합니다.");
}
}
Develope
package ioc.ioc6;
public class Develope {
private Emp emp;
private Emp emp2;
public Develope(Emp emp, Emp emp2) {
this.emp = emp;
this.emp2 = emp2;
}
void coding() {
emp.gotoOffice();
System.out.println("업무합니다....");
emp.getofWork();
emp2.gotoOffice();
System.out.println("emp2 업무합니다....");
emp2.getofWork();
}
}
3. Method Injection
Method 정의 전체에 Bean을 주입하는 것
Method Replace(메소드 대체)
기존 메소드를 런타임 중에 새로운 구현으로 대체
Magictian
package magic;
import lombok.Data;
@Data
public class Magician {
private MagicBox magicBox;
public void magic() {
System.out.println("마술시작");
System.out.println(magicBox.getContent());
System.out.println("짜잔");
}
}
MagicBox
package magic;
public interface MagicBox {
String getContent();
}
MagicBoxImpl
package magic;
public class MagicBoxImpl implements MagicBox{
@Override
public String getContent() {
return "비둘기";
}
}
Tiger
package magic;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class Tiger implements MethodReplacer{
@Override
public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
// invoke
// obj : 메서드 수행 객체
// method 메서드 자신
// args 파라미터
// return 반환값
return "호랑이";
}
}
maginc.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.xsd">
<!-- magicBox -->
<bean class="magic.MagicBoxImpl" id="magicBox" >
<replaced-method name="getContent" replacer="tiger" />
</bean>
<!-- magician -->
<bean class="magic.Magician" id="magician">
<property name="magicBox" ref="magicBox"></property>
</bean>
<!-- method replacer -->
<bean class="magic.Tiger" id="tiger" />
</beans>
Getter Injection(게터 주입)
기존 메소드를 런 타임중에 spring Context로 부터 특정한 빈을 반환하는 새로운 구현으로 대체. Method 주입의 특별한 경우로 Method가 특정 타입의 빈을 반환하도록 선언해 두고(보통 abstract) 런타임 중 실제 반환되는 빈은 Spring Context에서 오도록 하는 방법
Emp
package emp;
public abstract class Emp {
public Emp getEmp() {
return this;
}
public void work() {
getEmp().work(); // 주입된 getEmp() 메소드를 사용
};
// getEmp를 주입, Emp가 주입된다.
// Run-Time 중에 xml 파일로부터 빈을 주입받는다.
}
Programmer
package emp;
public class Programmer extends Emp{
@Override
public Emp getEmp() {
return this;
}
@Override
public void work() {
System.out.println("프로그래머의 개발");
}
}
Designer
package emp;
public class Designer extends Emp{
@Override
public Emp getEmp() {
return this;
}
@Override
public void work() {
System.out.println("디자이너의 디자인");
}
}
emp.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.xsd">
<bean class="emp.Programmer" id="programmer"></bean>
<bean class="emp.Designer" id="designer"></bean>
<!-- 아래 lookup-method는 메소드를 런타임 중에 새로운 구현으로 대체 getter 주입은 setter Injection의 역으로 생각
getEmp()를 호출할 때마다 다른 myemp가 반환, 그러나 setter Injection은 단 한번만 주입, 주입되는 메소드 명이
반드시 getXXX 로 시작할 필요는 없다.
-->
<bean class="emp.Emp" id="emp">
<lookup-method name="getEmp" bean="programmer"/>
</bean>
</beans>
EmpMain
package emp;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmpMain {
public static void main(String[] args) {
// Emp emp = new Programmer();
// emp.work();
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("emp.xml");
Emp emp = (Emp)ctx.getBean("emp");
Emp emp1 = (Emp)ctx.getBean("programmer");
emp.work(); // 추상클래스를 통한 객체 생성
emp1.work(); // 구상 클래스를 통한 객체 생성
ctx.close();
}
}
'Full Stack > Spring' 카테고리의 다른 글
[풀스택 과정] Spring Core : Spring IoC 및 DI(2) (0) | 2023.03.22 |
---|---|
[풀스택 과정] Spring Core : Spring IoC 및 DI (0) | 2023.03.22 |
[풀스택 과정] Spring Core : Spring이란? (0) | 2023.03.22 |
[풀스택 과정] Spring 설치(STS 3.9.4 version) (1) | 2023.03.16 |