2-5. Spring DI(Dependency Injection)
2-5-1. 세터 주입(Setter Injection) – XML 기반
세터주입은 클래스 사이의 의존관계를 연결시키기 위해 setter 메소드를 이용하는 방법이다.
[Emp.java]
package edu.ojc.setter1;
interface Emp {
public abstract void gotoOffice();
public abstract void getoffWork();
}
[Programmer.java]
package edu.ojc.setter1;
class Programmer implements Emp {
public void gotoOffice() {
System.out.println("프로그래머 출근 합니다.");
}
public void getoffWork() {
System.out.println("프로그래머 퇴근 합니다.");
}
}
[Designer.java]
package edu.ojc.setter1;
class Designer implements Emp {
public void gotoOffice() {
System.out.println("디자이너 출근 합니다.");
}
public void getoffWork() {
System.out.println("디자이너 퇴근 합니다.");
}
}
[Develop.java]
package edu.ojc.setter1;
public class Develope {
Emp emp;
public void setEmp(Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("개발합니다...");
emp.getoffWork();
}
}
[Src/main/resources/ojc1.xml] – p 네임스페이스를 이용한 세터주입
<?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 id="programmer" class="edu.ojc.setter1.Programmer" />
<bean id="designer" class="edu.ojc.setter1.Designer" />
<bean id="develope" class="edu.ojc.setter1.Develope" p:emp-ref="programmer" />
<!--
//아래처럼 Property 태그를 이용해도 된다.
<bean id="develope" class="edu.ojc.setter1.Develope">
<property name="emp“><ref bean="programmer"/></property>
</bean>
<bean id="develope" class="edu.ojc.setter1.Develope">
<property name="emp" ref="programmer"/> </bean>
-->
</beans>
[TestMain.java]
package edu.ojc.setter1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ojc1.xml");
Develope dev = (Develop)context.getBean("develope");
dev.coding();
}
}
2-5-2. 세터 주입(Setter Injection) – 어노테이션 기반
[Emp.java]
package edu.ojc.setter2;
interface Emp {
public abstract void gotoOffice();
public abstract void getoffWork();
}
[Programmer.java]
package edu.ojc.setter2;
import org.springframework.stereotype.Service;
@Service
class Programmer implements Emp {
public void gotoOffice() {
System.out.println("프로그래머 출근 합니다.");
}
public void getoffWork() {
System.out.println("프로그래머 퇴근 합니다.");
}
}
[Designer.java]
package edu.ojc.setter2;
import org.springframework.stereotype.Service;
@Service
class Designer implements Emp {
public void gotoOffice() {
System.out.println("디자이너 출근 합니다.");
}
public void getoffWork() {
System.out.println("디자이너 퇴근 합니다.");
}
}
[Develop.java]
package edu.ojc.setter2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class Develope {
Emp emp;
@Autowired
@Qualifier("programmer")
public void setEmp(Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("개발합니다...");
emp.getoffWork();
}
}
[Src/main/resources/ojc2.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: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">
<context:component-scan base-package="edu.ojc.setter2"/>
</beans>
[TestMain.java]
package edu.ojc.setter2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ojc1.xml");
Develope dev = (Develop)context.getBean("develope");
dev.coding();
}
}
2-5-3. 생성자 주입(Constructor Injection) – XML 기반
[Emp.java]
package edu.ojc.constructor1;
interface Emp {
public abstract void gotoOffice();
public abstract void getoffWork();
}
[Programmer.java]
package edu.ojc.constructor1;
class Programmer implements Emp {
public void gotoOffice() {
System.out.println("프로그래머 출근 합니다.");
}
public void getoffWork() {
System.out.println("프로그래머 퇴근 합니다.");
}
}
[Designer.java]
package edu.ojc.constructor1;
class Designer implements Emp {
public void gotoOffice() {
System.out.println("디자이너 출근 합니다.");
}
public void getoffWork() {
System.out.println("디자이너 퇴근 합니다.");
}
}
[Develop.java]
package edu.ojc.constructor1;
public class Develope {
Emp emp;
public Develope(Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("개발합니다...");
emp.getoffWork();
}
}
[Src/main/resources/ojc3.xml] – C 네임스페이스를 이용한 세터주입
<?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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="programmer" class="edu.ojc.constructor1.Programmer" />
<bean id="designer" class="edu.ojc.constructor1.Designer" />
<bean id="develope" class="edu.ojc.constructor1.Develope" c:emp-ref="programmer" />
<!--
<bean id="develope" class="edu.ojc.constructor1.Develope">
<constructor-arg ref="programmer"/>
</bean>
-->
</beans>
[TestMain.java]
package edu.ojc.constructor1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ojc3.xml");
Develope dev = (Develope)context.getBean("develope");
dev.coding();
}
}
2-5-4. 생성자 주입(Constructor Injection) – 어노테이션 기반
[Emp.java]
package edu.ojc.constructor2;
interface Emp {
public abstract void gotoOffice();
public abstract void getoffWork();
}
[Programmer.java]
package edu.ojc.constructor2;
import org.springframework.stereotype.Service;
@Service
class Programmer implements Emp {
public void gotoOffice() {
System.out.println("프로그래머 출근 합니다.");
}
public void getoffWork() {
System.out.println("프로그래머 퇴근 합니다.");
}
}
[Designer.java]
package edu.ojc.constructor2;
import org.springframework.stereotype.Service;
@Service
class Designer implements Emp {
public void gotoOffice() {
System.out.println("디자이너 출근 합니다.");
}
public void getoffWork() {
System.out.println("디자이너 퇴근 합니다.");
}
}
[Develop.java]
package edu.ojc.constructor2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class Develope {
Emp emp;
@Autowired
public Develope(@Qualifier(value="programmer") Emp emp) {
this.emp = emp;
}
void coding() {
emp.gotoOffice();
System.out.println("개발합니다...");
emp.getoffWork();
}
}
[Src/main/resources/ojc4.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: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">
<context:component-scan base-package="edu.ojc.constructor2"/>
</beans>
[TestMain.java]
package edu.ojc.constructor2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("ojc4.xml");
Develope dev = (Develop)context.getBean("develope");
dev.coding();
}
}
2-5-5. 메소드 주입(Method Injection)
Method 정의 전체에 Bean을 주입하는 것으로 Method Replace와 Getter Injection으로 구별할 수 있다.
Method Replace(메소드 대체) : 기존 메소드를 런타임 중에 새로운 구현으로 대체
Getter Injection(게터 주입) : 기존 메소드를 런 타임중에 spring Context로 부터 특정한 빈을 반환하는 새로운 구현으로 대체. Method 주입의 특별한 경우로 Method가 특정 타입의 빈을 반환하도록 선언해 두고(보통 abstract) 런타임 중 실제 반환되는 빈은 Spring Context에서 오도록 하는 방법
2-5-5-1. Method Injection(Method Replace)
[Emp.java]
package ojc1;
public interface Emp {
public String work();
}
[Programmer.java]
package ojc1;
public class Programmer implements Emp {
public String work() {
return "Programmer Working...";
}
}
[Designer.java]
package ojc1;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
import org.springframework.stereotype.Service;
public class Designer implements MethodReplacer {
public Object reimplement(Object target, Method method, Object[] args) throws Throwable {
return "Designer Working...";
}
}
[MethodReplaceTest.java]
package ojc1;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MethodReplaceTest {
Emp programmer;
public void setProgrammer(Programmer programmer) {
this.programmer = programmer;
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("lookup.xml");
MethodReplaceTest test = (MethodReplaceTest) context.getBean("methodReplaceTest");
//Programmer의 work()가 아닌 대체자인 Designer의 work()가 실행됨
System.out.println(test.programmer.work());
}
}
[/src/main/resources/lookup.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="programmer" class="ojc1.Programmer">
<replaced-method name="work" replacer="designer" />
</bean>
<bean id="designer" class="ojc1.Designer" />
<bean id="methodReplaceTest" class="ojc1.MethodReplaceTest">
<property name="programmer" ref="programmer"/>
</bean>
</beans>
2-5-5-2. Method Injection(Getter Injection)
[Emp.java]
package ojc2;
public abstract class Emp {
public Emp() {}
public void work() {
getEmp().work(); //주입받은 객체의 getEmp() 메소드를 사용
}
//getEmp를 주입, Emp가 주입된다.
//Run-Time중에 xml 파일로 부터 빈을 주입받는다.
public abstract Emp getEmp() ;
}
[Programmer.java]
package ojc2;
public class Programmer extends Emp{
public Emp getEmp() {
return this;
}
public void work() {
System.out.println("프로그래머가 개발을 합니다.");
}
}
[Designer.java]
package ojc2;
public class Designer extends Emp{
public Emp getEmp() {
return this;
}
public void work() {
System.out.println("디자이너가 디자인을 합니다.");
}
}
[/src/main/resources/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-4.2.xsd">
<!-- <bean id="myemp" class="ojc2.Designer" /> -->
<bean id="myemp" class="ojc2.Programmer" />
<!-- 아래 lookup-method는 메소드를 런타입중에 새로운 구현으로 대체 Getter주입은 Setter Injection의 역으로 생각. getEmp()를 호출할 때마다 다른 myemp가 반환 그러나 Setter Injectioin은 단 한번만 주입 주입되는 메소드명이 반드시 getXXX로 시작할 필요는 없다. -->
<bean id="emp" class="ojc2.Emp">
<lookup-method name="getEmp" bean="myemp" />
</bean>
</beans>
[EmpTest.java]
package ojc2;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmpTest {
public static void main(String[] args) throws Exception{
ApplicationContext ctx = new ClassPathXmlApplicationContext("emp.xml");
Emp emp = (Emp) ctx.getBean("emp");
emp.work();
}
}
#세터주입, #생성자주입, #메소드주입, #스프링교육, #스프링강의, #injection, #SpringInjection, #setterinjection